2010-04-06 9 views
10

Tôi cần phải tạo động các thuộc tính lớp từ từ DEFAULTS.Tự động tạo thuộc tính lớp

defaults = { 
    'default_value1':True, 
    'default_value2':True, 
    'default_value3':True, 
} 

class Settings(object): 
    default_value1 = some_complex_init_function(defaults[default_value1], ...) 
    default_value2 = some_complex_init_function(defaults[default_value2], ...) 
    default_value3 = some_complex_init_function(defaults[default_value3], ...) 

Tôi cũng có thể đạt được điều này bằng cách có sth. như __init__ để tạo lớp học, để tự động tạo các thuộc tính này từ từ điển và lưu nhiều mã và công việc ngu xuẩn.

Bạn sẽ làm như thế nào?

Cảm ơn bạn rất nhiều trước!

Trả lời

3

Tôi nghĩ đó là trường hợp cho metaclass:

class SettingsMeta(type): 
    def __new__(cls, name, bases, dct): 
     for name, value in defaults.items(): 
      dct[name] = some_complex_init_function(value, ...) 
     return type.__new__(cls, name, bases, dct) 

class Settings(object): 
    __metaclass__ = SettingsMeta 
+2

làm thế nào để chúng ta vượt qua giá trị mặc định, hoặc làm thế nào chúng ta có thể khởi tạo bất kỳ đối tượng Cài đặt lớp –

+1

cùng câu hỏi này với @vijayshanker – TomSawyer

+0

Mã này phụ thuộc vào 'từ điển defaults' đang trong phạm vi khi xác định lớp 'Cài đặt'. –

19

Bạn có thể làm điều đó mà không metaclasses sử dụng trang trí. Bằng cách này, IMO rõ ràng hơn một chút:

def apply_defaults(cls): 
    defaults = { 
     'default_value1':True, 
     'default_value2':True, 
     'default_value3':True, 
    } 
    for name, value in defaults.items(): 
     setattr(cls, name, some_complex_init_function(value, ...)) 
    return cls 

@apply_defaults 
class Settings(object): 
    pass 

Trước khi trang trí lớp học 2.6 không có sẵn. Vì vậy, bạn có thể viết:

class Settings(object): 
    pass 
Settings = apply_defaults(Settings) 

trong phiên bản cũ của python.

Trong ví dụ được cung cấp apply_defaults là tái sử dụng ... Vâng, ngoại trừ giá trị mặc định được mã hóa cứng trong cơ thể của trang trí :) Nếu bạn có chỉ là một trường hợp duy nhất bạn thậm chí có thể đơn giản hóa mã của bạn như thế này:

defaults = { 
    'default_value1':True, 
    'default_value2':True, 
    'default_value3':True, 
} 

class Settings(object): 
    """Your implementation goes here as usual""" 

for name, value in defaults.items(): 
    setattr(Settings, name, some_complex_init_function(value, ...)) 

Điều này là có thể vì các lớp (theo nghĩa các loại) là các đối tượng trong Python.

+1

Bạn cũng cần trả về lớp "trang trí" ('cls' trong ví dụ đầu tiên) ở cuối hàm trang trí, phải không? Đã cho tôi một thời gian để tìm ra, nhưng trừ khi tôi làm điều này lớp sẽ bằng 'None' sau khi định nghĩa. Tôi có thiếu một cái gì đó, ví dụ như một số cách để cung cấp các lớp học bằng cách tham khảo để thay thế? – Simon

+0

Một cách thanh lịch. – zoujyjs

+0

Làm cách nào để chuyển mặc định cho tệp như thế này 'a = Cài đặt (mặc định) '' settings.py' là một tệp cụ thể – TomSawyer

0

Khi xác định một lớp, không gian tên cục bộ sẽ được chuyển đổi thành không gian tên lớp khi kết thúc nội dung lớp. Như vậy, bạn có thể thực hiện điều này với:

class Settings(object): 
    for key, val in defaults.iteritems(): 
     locals()[key] = some_complex_init_function(val, ...) 
+1

-1 [tài liệu] (http://docs.python.org/library/functions. html? highlight = locals # locals) cho 'locals()' cho biết nội dung của từ điển được trả về không được sửa đổi. – martineau

+0

Điều này là thông minh. Cảm ơn. –