>>> print(ObjectCreator) # you can print a class because it's an object <class '__main__.ObjectCreator'> ================================= >>> defecho(o): ... print(o) ... >>> echo(ObjectCreator) # you can pass a class as a parameter <class '__main__.ObjectCreator'> ================================= >>> print(hasattr(ObjectCreator, 'new_attribute')) False >>> ObjectCreator.new_attribute = 'foo'# you can add attributes to a class >>> print(hasattr(ObjectCreator, 'new_attribute')) True >>> print(ObjectCreator.new_attribute) foo ================================= >>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable >>> print(ObjectCreatorMirror.new_attribute) foo >>> print(ObjectCreatorMirror()) <__main__.ObjectCreator object at 0x8997b4c>
动态创建类
因为类也是对象,所以和其他任何的对象一样,我们可以即时(on the fly)创建一个类。
比如,在函数中创建类
1 2 3 4 5 6 7 8 9
>>> defchoose_class(name): ... if name == 'foo': ... classFoo(object): ... pass ... return Foo # return the class, not an instance ... else: ... classBar(object): ... pass ... return Bar
# the metaclass will automatically get passed the same argument # that you usually pass to `type` defupper_attr(future_class_name, future_class_parents, future_class_attrs): """ Return a class object, with the list of its attribute turned into uppercase. """ # pick up any attribute that doesn't start with '__' and uppercase it uppercase_attrs = { attr if attr.startswith("__") else attr.upper(): v for attr, v in future_class_attrs.items() }
# let `type` do the class creation returntype(future_class_name, future_class_parents, uppercase_attrs)
__metaclass__ = upper_attr # this will affect all classes in the module
classFoo():# global __metaclass__ won't work with "object" though # but we can define __metaclass__ here instead to affect only this class # and this will work with "object" children bar = 'bip'
# remember that `type` is actually a class like `str` and `int` # so you can inherit from it classUpperAttrMetaclass(type): # __new__ is the method called before __init__ # it's the method that creates the object and returns it # while __init__ just initializes the object passed as parameter # you rarely use __new__, except when you want to control how the object # is created. # here the created object is the class, and we want to customize it # so we override __new__ # you can do some stuff in __init__ too if you wish # some advanced use involves overriding __call__ as well, but we won't # see this def__new__(upperattr_metaclass, future_class_name, future_class_parents, future_class_attrs): uppercase_attrs = { attr if attr.startswith("__") else attr.upper(): v for attr, v in future_class_attrs.items() } returntype(future_class_name, future_class_parents, uppercase_attrs)
接下来,然我们用更规范、更简短的方式重新写一下上面这个类
1 2 3 4 5 6 7
classUpperAttrMetaclass(type): def__new__(cls, clsname, bases, attrs): uppercase_attrs = { attr if attr.startswith("__") else attr.upper(): v for attr, v in attrs.items() } returntype(clsname, bases, uppercase_attrs)
classUpperAttrMetaclass(type): def__new__(cls, clsname, bases, attrs): uppercase_attrs = { attr if attr.startswith("__") else attr.upper(): v for attr, v in attrs.items() } returntype.__new__(cls, clsname, bases, uppercase_attrs)
还可以用super,这样更加简洁,也更加容易继承。
1 2 3 4 5 6 7 8
classUpperAttrMetaclass(type): def__new__(cls, clsname, bases, attrs): uppercase_attrs = { attr if attr.startswith("__") else attr.upper(): v for attr, v in attrs.items() } returnsuper(UpperAttrMetaclass, cls).__new__( cls, clsname, bases, uppercase_attrs)