Python元类

2017-02-08  本文已影响0人  FangHao

类也是对象

在Python中一切都是对象,类也不例外。所以可以对类进行以下操作。
1.可以当做参数传递
2.可以添加属性
3.可以赋给变量

代码如下:

#coding=utf-8
class Person():
pass

# 可以赋值
print(Person())
p = Person()
print(p)

# 可以当做参数传递
def printClass(patern):
print(patern)
printClass(Person())

# 可以添加属性

Person.name = 'Python'
print(Person.name)

运行结果如下:

type

type其实就是元类,type的作用有两个,第一是查看对象的类型(也可以理解为这个对象是由什么创建创建出来的),第二是可以创建类
代码如下:

#coding=utf-8
class Person():
pass

print(type(Person))
print(type(type(Person)))

运行结果如下:

所以我们可以知道所有的类都是由type创建出来的,如果print(type(type)),最终显示的还是type(这里应该是采用了一个递归的方式)

使用type创建类

代码如下:

#coding=utf-8
Test1Class = type('Test1',(),{})
test1 = Test1Class()
print(test1)

Test2Class = type('Test2',(Test1Class,),{'num':100})
test2 = Test2Class()
print(test2)
print(test2.num)

def __init__(self,age):
self.age = age

def instancemethod(self,name):
print('实例方法')
print(name)
print(self.age)

@classmethod
def classmethod(cls):
print('类方法')
cls.numtest3 = 300

@staticmethod
def staticmethod():
print('hello world')
#print(numtest3)


Test3Class = type('Test3',(Test2Class,),{'__init__':__init__,'instance':instancemethod,'class3':classmethod,'static':staticmethod,'numtest3':200})
test3 = Test3Class(18)
print(test3)
print(test3.instance('xiaohua'))
print(test3.numtest3)
print(test3.class3())
print(test3.static())
print(test3.num)
print(test3.numtest3)

运行结果如下:

metaclass

class中的变量__metaclass__可以来决定类是由谁来创建
代码如下:

#coding=utf-8

class UpperAttrMetaClass(type):
#__new__方法默认需要传cls参数、后面三个参数依次代表:类名,类的集成,类的属性。默认由系统传递
def __new__(cls,future_class_name,future_class_parents,future_class_attr):
# 取出future_class_attr中属性名以__开头的,并保存在attrs这个元组中
attrs = ((name,value) for name,value in future_class_attr.items() if not name.startswith('__'))
# 将attrs元组再解开然后将其中name改为大写,改成字典保存到uppercase_attrs中
uppercase_attrs = dict((name.upper(),value) for name,value in attrs)

# 1.通过type来做类对象的创建
# return type(future_class_name,future_class_parents,uppercase_attrs)

# 2.通过复用type.__new__的方法来创建类对象
# return type.__new__(cls,future_class_name,future_class_parents,future_class_attr)

# 3.通过super方法创建类对象
return super(UpperAttrMetaClass,cls).__new__(cls,future_class_name,future_class_parents,future_class_attr)

# python2用法,python3也能用
class Foo(object):
__metaclass__ = UpperAttrMetaClass
bar = 'bip'

# python3用法
# class Foo(object,metaclass = UpperAttrMetaClass):
# bar = 'bip'

# hasattr用来检测类中是否有某属性
print(hasattr(Foo,'bar'))
print(hasattr(Foo,'BAR'))

Python做了如下的操作:

  1. Foo中有metaclass这个属性吗?如果是,Python会通过metaclass创建一个名字为Foo的类(对象)
  2. 如果Python没有找到metaclass,它会继续在Bar(父类)中寻找metaclass属性,并尝试做和前面同样的操作。
  3. 如果Python在任何父类中都找不到metaclass,它就会在模块层次中去寻找metaclass,并尝试做同样的操作。
  4. 如果还是找不到metaclass,Python就会用内置的type来创建这个类对象。
上一篇 下一篇

猜你喜欢

热点阅读