1 Python中的type函数
def fn(self ,name="world"):
print ("hello",name)
Hello=type("Hello",(object,),{"hello":fn})
h=Hello()
h.hello()
Python中可以使用type函数创建一个类,其中type函数的第一个参数为类的名字,第二个参数是这个类的父类,是一个列表类型;第三个参数是一个字典类型 ,表示类中的属性。在上面的例子中我们指定该类有一个hello属性,这个hello属性指向一个函数fn。返回值是一个类的名字。
2 类的class属性
print h.__class__
print Hello.__class__
<class '__main__.Hello'>
<type 'type'>
class 属性表示谁创建了这个对象,对于h对象来说显然是Hello类创建这个对象;对于Hello类来说,是type类创建这个 class对象。type是元类,默认情况下所有的类Class都是由type类创建。
3 metaclass 属性
我们可以在定义一个类的时候为其添加metaclass 属性。
class Foo(object):
_metaclass=something
metaclass属性指定了谁来创建我们的类。
Python在加载模块的时候会加载类中的代码,比如说 会执行类中定义的输出语句,并且声明定义的方法,但是并不会执行模块中的方法也不会执行类中的方法
class Person(object):
print"this is person class"
def __init__(self,pName):
self.name=pName
上面在加载类的时候将会输出 this is a person class 但是并不会执行init方法。
因此当我们在定义类的时候如果指定了metaclass 属性,那么这个类就有了一个metaclass属性,在创建这个类的时候将会取决于metaclass 所指向 的属性。metaclass就是元类的代码,将会创建出一个类。
如果我们在代码中指定了metaclass 属性,那么将来创建类的时候将会使用metaclass。 如果我们在类中没有定义metaclass那么 ,那么就会到父类中寻找是否存在,如果还是没有那么就使用Python默认的元类(metaclass指向的代码)创建类对象
def upper_attr(future_class_name, future_class_parents ,future_class_attr):
#遍历函数的属性, 将不是_开头的属性名字变为大写
newAtrr={}
for name ,value in future_class_attr.items():
if not name.startswith("_"):
newAtrr[name.upper()]=value
return type(future_class_name,future_class_parents,newAtrr)
class Foo(object):
__metaclass__=upper_attr
bar="bip"
print(hasattr(Foo,"bar"))
print (hasattr(Foo,"BAR"))
输出:
False
True
上面 因为Foo 类定义了metaclass属性,所以在创建类的时候,类名Foo将会被传入到upper_attr方法中作为第一个参数, Foo类的父类列表将会作为第二个参数传入到upper_attr方法中作为第二个参数, Foo类中定义的属性组成一个字典将会作为upper_attr的第三个参数传入到upper_attr方法中。
在upper_attr方法中首先是遍历future_class_attr 字典对象,如果当前属性名称不是以_ 开头,那么将这个属性名称转为大写。 upper_attr方法 最后返回一个使用type函数创建的类 ,这个类就是Foo类。
通过metaclass属性我们控制了Foo类的创建。
从上面的输出我们看到 Foo类没有bar属性,而是存在着BAR属性。
4 python 3 中 metaclass的使用
在Python2中,metaclass的使用方式如上。在Python3中,Python2中的metaclass 改为了metaclass,并且应该书写格式如下:
class Foo(object,metaclass=upper_attr):
bar="bip"
网友评论