2010-02-15 27 views
8

Tôi đã cố gắng để tạo ra một lớp từ một cuốn từ điển:Thêm lớp thuộc tính sử dụng một vòng lặp for trong Python

class attr: 
    for key in objects_type: 
     setattr(attr, key, lambda cl: list()) 

này cung cấp cho các lỗi mà attr không được định nghĩa trong vòng lặp for. Tôi biết tôi có thể viết:

class attr: 
    pass 
for key in objects_type: 
    setattr(attr, key, lambda cl: list()) 

Nhưng tôi chắc chắn tôi nhớ nhìn thấy mã tương tự như ví dụ đầu tiên ở đâu đó. Có ai biết nếu nó có thể viết một cái gì đó tương tự như hình thức đầu tiên?

Trả lời

6

Mặc dù nó không phải rất thanh lịch, bạn có thể sử dụng locals():

>>> class c(object): 
...  for i in range(10): 
...   locals()['A' + str(i)] = i 
... 
>>> c.A0 
0 
>>> c.A7 
7 
+0

Đó phải là những gì tôi nhớ nhìn thấy. Cảm ơn – Casebash

+0

Trong thực tế, tôi nghĩ rằng nó là đẹp hơn bằng cách sử dụng setattr - vì vậy tôi sẽ không nói không phù hợp của nó ở tất cả – Casebash

+6

Bạn không được phép thay đổi người dân địa phương() dict: http://docs.python.org/library/functions .html # locals – stephan

2

Tôi không biết chính xác, bạn đang làm gì. Tôi có thể cung cấp cho bạn ví dụ về việc thêm thuộc tính lớp vào một lớp học trong vòng lặp for:

attributes = ('x', 5), ('y', 6), ('name', 'Cls') 

class Cls: 
    pass 
for key, value in attributes: 
    setattr(Cls, key, value) 

Hãy nhớ rằng phải chạy sau khi toàn bộ lớp được xác định. Bạn nhận được lỗi, attr đó không được xác định, bởi vì bạn muốn truy cập vào lớp trước bạn tạo nó (class ... là một câu lệnh trong python, tạo ra một đối tượng lớp). Bạn phải thêm các thuộc tính sau khi bạn tạo một lớp và ghi nhớ, các thuộc tính đó sẽ là các thuộc tính lớp, chứ không phải các thuộc tính của cá thể.

1
class Attr: 
    def __init__(self): 
    for key in objects_type: 
     setattr(Attr, key, lambda cl: list()) 
+1

+1: Tốt. Tại sao không phải là một lớp "kiểu mới" kế thừa từ 'đối tượng'? –

+2

Đây là nơi sai để thực hiện việc này. Không chỉ là lãng phí, nhưng các phương thức ràng buộc hiện tại sẽ khác với các phương thức ràng buộc từ các đối tượng được khởi tạo sau này. Vâng, khác biệt hơn bình thường. –

2
newmeths = { 
    'two': lambda self: 2, 
} 

class MC(type): 
    def __init__(cls, name, bases, dict): 
    for k, v in newmeths.iteritems(): 
     setattr(cls, k, v) 
    super(MC, cls).__init__(name, bases, dict) 

class C(object): 
    __metaclass__ = MC 
    pass 

c=C() 
print c.two() 
3

giả sử bạn muốn tự động thêm thuộc tính lớp như thế này

classDict = {} 
for i in range(2): 
    classDict["func%s"%(i+1)] = lambda self:"X" 

bạn có thể làm điều này theo một số cách, ví dụ chỉ cần thêm thuộc tính sau khi lớp học đã được tạo vì bạn có thể dễ dàng truy cập vào tên lớp trong lớp

class Attr2(object): 
    pass 

for n,v in classDict.iteritems(): 
    setattr(Attr2, n, v) 

print Attr2().func1(), Attr2().func2() 

hoặc tốt hơn là chỉ tạo lớp học ngay tức khắc.

Attr3 = type("Attr3",(), classDict) 
print Attr3().func1(), Attr3().func2() 

hoặc nếu bạn muốn sử dụng metaclass ví dụ

class AttrMeta(type): 
    def __new__(cls, name, bases, dct): 
     dct.update(classDict) 
     return type.__new__(cls, name, bases, dct) 

class Attr4(object): 
    __metaclass__ = AttrMeta 

print Attr4().func1(), Attr4().func2() 
+1

Tôi nghĩ phương pháp 'type' là giải pháp tốt nhất, đưa ra câu hỏi. Nó yêu cầu người lập trình phải cấu trúc lại phần còn lại của các thuộc tính lớp được định nghĩa như thế nào. Mặt khác, nó tránh đào vào 'locals()', tránh xác định một metaclass tùy chỉnh, và tránh mucking với logic của bất kỳ metaclasses _other_ nào được sử dụng. IMO, điều này làm cho nó ngon miệng cho một thư viện mà người khác sẽ sử dụng và đóng góp. – AlanSE

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