2010-02-09 67 views
16

Vì vậy, tôi có một tập hợp các lớp và một chuỗi với một trong các tên lớp. Làm thế nào để tạo một lớp dựa trên chuỗi đó?Khởi tạo một lớp Python từ tên

class foo: 
    def __init__(self, left, right): 
    self.left = left 
    self.right = right 

str = "foo" 
x = Init(str, A, B) 

Tôi muốn x là sự khởi tạo của lớp foo.

+2

Trùng lặp. http://stackoverflow.com/questions/734970/python-reference-to-a-class-from-a-string, http://stackoverflow.com/questions/1176136/convert-string-to-python-class- đối tượng, http://stackoverflow.com/questions/553784/can-you-use-a-string-to-instantiate-a-class-in-python, v.v. –

Trả lời

13

Nếu bạn biết không gian tên tham gia, bạn có thể sử dụng nó trực tiếp - ví dụ, nếu tất cả các lớp học nằm trong mô-đun zap, từ điển vars(zap) là namespace đó; nếu tất cả chúng nằm trong mô-đun hiện tại, globals() có lẽ là cách dễ nhất để có được từ điển đó.

Nếu các lớp không phải là tất cả trong cùng một không gian tên, sau đó xây dựng một không gian tên "nhân tạo" (một tên chuyên dụng với tên lớp là khóa và đối tượng lớp làm giá trị), như @Ignacio gợi ý, có lẽ là cách tiếp cận đơn giản nhất.

6
classdict = {'foo': foo} 

x = classdict['foo'](A, B) 
+2

Tôi có thể làm điều đó bằng cách sử dụng sự phản chiếu như thế nào? – klynch

+0

Bạn * có thể * sử dụng 'getattr()', nhưng điều đó có thể khiến bạn gặp vấn đề về bảo mật. Sử dụng một trình trang trí lớp sẽ cho phép bạn liệt kê các lớp tự động, nhưng chúng chỉ tồn tại trong các phiên bản Python mới hơn. –

+0

Bạn sẽ sử dụng trang trí như thế nào?Nó sẽ nối thêm vào một danh sách các lớp có thể khởi tạo được - và tôi sẽ phải lặp qua danh sách này để chọn đúng lớp để khởi tạo? –

15

Trong trường hợp của bạn, bạn có thể sử dụng một cái gì đó giống như

get_class = lambda x: globals()[x] 
c = get_class("foo") 

Và nó thậm chí còn dễ dàng hơn không get lớp từ các module

import somemodule 
getattr(somemodule, "SomeClass") 
2
classname = "Foo" 
foo = vars()[classname](Bar, 0, 4) 

Hoặc có lẽ

def mkinst(cls, *args, **kwargs): 
    try: 
     return globals()[cls](*args, **kwargs) 
    except: 
     raise NameError("Class %s is not defined" % cls) 

x = mkinst("Foo", bar, 0, 4, disc="bust") 
y = mkinst("Bar", foo, batman="robin") 

ghi chú khác trên đoạn:

*args**kwargs là các thông số đặc biệt trong Python, họ có nghĩa là «một mảng args phi từ khóa» và «một dict của từ khóa args »cho phù hợp.

PEP-8 (hướng dẫn kiểu Python chính thức) đề xuất sử dụng cls cho biến lớp học.

vars() trả về một biến số của các biến được xác định trong phạm vi cục bộ.

globals() trả về một biến số của các biến hiện có trong môi trường bên ngoài phạm vi địa phương.

1

Bạn có thể cân nhắc sử dụng metaclass cũng như:

Cls = type('foo',(), foo.__dict__) 
x = Cls(A, B) 

Tuy nhiên, nó tạo ra một lớp học tương tự.

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