2009-06-05 35 views
5

Có thể tạo thuộc tính trên đối tượng trình tạo không?python: thuộc tính trên đối tượng máy phát

Dưới đây là một ví dụ rất đơn giản:

def filter(x): 
    for line in myContent: 
     if line == x: 
      yield x 

Bây giờ nói rằng tôi có rất nhiều những phát lọc các đối tượng nổi xung quanh ... có thể một số trong số đó là vô danh ... Tôi muốn quay trở lại sau đó và thẩm vấn cho những gì họ lọc. Có cách nào tôi có thể a) thẩm vấn đối tượng máy phát điện cho giá trị của x hoặc b) đặt một thuộc tính với giá trị của x mà sau này tôi có thể thẩm vấn không?

Cảm ơn

Trả lời

6

Thật không may, đối tượng máy phát điện (kết quả trả về từ gọi hàm phát) không hỗ trợ thêm thuộc tính tùy ý. Bạn có thể làm việc xung quanh nó ở một mức độ nào đó bằng cách sử dụng một dict bên ngoài được lập chỉ mục bởi các đối tượng máy phát, vì các đối tượng như vậy có thể sử dụng làm khóa thành một dict. Vì vậy, nơi bạn muốn như để làm, nói:

a = filter(23) 
b = filter(45) 
... 
a.foo = 67 
... 
x = random.choice([a,b]) 
if hasattr(x, 'foo'): munge(x.foo) 

bạn thay vì có thể làm:

foos = dict() 
a = filter(23) 
b = filter(45) 
... 
foos[a] = 67 
... 
x = random.choice([a,b]) 
if x in foos: munge(foos[x]) 

Đối với bất cứ điều gì fancier, sử dụng một lớp thay vì một máy phát điện (một hoặc nhiều lớp của phương pháp có thể là máy phát điện, sau khi tất cả).

16

Có.

class Filter(object): 
    def __init__(self, content): 
     self.content = content 
    def __call__(self, someParam): 
     self.someParam = someParam 
     for line in self.content: 
      if line == someParam: 
       yield line 
2

No. Bạn không thể đặt thuộc tính tùy ý trên máy phát.

Như S. Lott chỉ ra, bạn có thể có đối tượng trông như máy phát điện và hoạt động như máy phát điện. Và nếu nó trông giống như một con vịt, và hành động như một con vịt, bạn đã có chính mình định nghĩa về cách gõ vịt, ngay tại đó.

Nó sẽ không hỗ trợ các thuộc tính trình tạo như gi_frame mà không có phương pháp proxy thích hợp.

0

Suy nghĩ về sự cố, có cách để máy phát điện mang theo một nhóm thuộc tính. Đó là một chút điên rồ - Tôi khuyên bạn nên đề nghị Alex Martelli thay vì điều này - nhưng nó có thể hữu ích trong một số tình huống.

my_content = ['cat', 'dog days', 'catfish', 'dog', 'catalog'] 

def filter(x): 
    _query = 'I\'m looking for %r' % x 

    def _filter(): 
     query = yield None 
     for line in my_content: 
      while query: 
       query = yield _query 

      if line.startswith(x): 
       query = yield line 

     while query: 
      query = yield _query 

    _f = _filter() 
    _f.next() 
    return _f 

for d in filter('dog'): 
    print 'Found %s' % d 

cats = filter('cat') 
for c in cats: 
    looking = cats.send(True) 
    print 'Found %s (filter %r)' % (c, looking) 

Nếu bạn muốn hỏi máy phát những gì nó lọc, chỉ cần gọi send với giá trị đánh giá là đúng. Tất nhiên, mã này có lẽ quá thông minh một nửa. Sử dụng cẩn thận.

3

Nếu bạn muốn thẩm vấn họ cho mục đích gỡ lỗi, sau đó các chức năng sau đây sẽ giúp:

import inspect 

def inspect_generator(g): 
    sourcecode = open(g.gi_code.co_filename).readlines() 
    gline = g.gi_code.co_firstlineno 
    generator_code = inspect.getblock(sourcecode[gline-1:]) 

    output = "Generator %r from %r\n" % (g.gi_code.co_name, g.gi_code.co_filename) 
    output += "".join("%4s: %s" % (idx+gline, line) for idx, line in enumerate(generator_code)) 

    output += "Local variables:\n" 
    output += "".join("%s = %r\n" % (key,value) for key,value in g.gi_frame.f_locals.items()) 

    return output 

print inspect_generator(filter(6)) 
"""Output: 
Generator 'filter' from 'generator_introspection.py' 
    1: def filter(x): 
    2:  for line in myContent: 
    3:   if line == x: 
    4:    yield x 
Local variables: 
x = 6 
""" 

Nếu bạn muốn thẩm vấn họ để thực hiện chức năng sau đó các lớp học thực hiện các giao thức iterator có lẽ là một ý tưởng tốt hơn.

0

Tôi nhận ra đây là một câu trả lời rất muộn, nhưng ...

Thay vì lưu trữ và sau đó đọc một số thuộc tính bổ sung, mã của bạn có thể sau đó chỉ kiểm tra biến của máy phát (s), sử dụng:

filter.gi_frame.f_locals

tôi đoán Ants Aasma ám chỉ đó.

+0

Tôi đã thử đề xuất của bạn để kiểm tra các biến của trình tạo. Nó hoạt động cho đến nay như 'StopIteration' vẫn chưa đạt được. Sau đó, 'gi_frame' trở thành' None'. – bli

Các vấn đề liên quan