class Animal(object):
"""a class representing an animal"""
def __init__(self,name):
self.name = name
def eat(self):
pass
def go_to_vet(self):
pass
animal = Animal('cat')
print(type(Animal))
print(animal)
#用type方式创建类******************************************************************
def init(self,name):
self.name = name
def eat(self):
pass
def go_to_vet(self):
pass
Animal = type('Animal',(object,),
{'__doc__':"a class representing an animal",'__init__':init,
'eat':eat,'go_to_vet':go_to_vet})
animal = Animal('dog')
print(animal)
#创建子类
def meow(self):
return None
def purr(self):
return None
Cat = type('Cat',(Animal,),{
'meow':meow,
'purr':purr
})
cat = Cat(name='xiaohuang')
print(cat)
print(type(Cat))
#元类示例******************************************************************
class Meta(type):
"""a metaclass that adds no actual functionality"""
def _(cls,name,bases,attrs):
"""
:param name: 类型:字符串 类名
:param bases: 类型:元组,继承的基类
:param attrs: 类型:字典 属性
:return: 类
"""
return super(Meta, cls).__new__(cls,name,bases,attrs)
#何时使用元类******************************************************************
# 1.说明性类声明,现有示例django模型声明
# 2.类验证 (foo 和 bar属性两个只能包含一个)
class FooOrbar(type):
def __new__(cls, name,bases,attrs):
if 'foo' in attrs and 'bar' in attrs:
raise TypeError('Class %s cannot contain both foo and bar'%name)
if 'foo' not in attrs and 'bar' not in attrs:
raise TypeError('Class %s must provide either foo or bar'%name)
return super(FooOrbar,cls).__new__(cls,name,bases,attrs)
class Valid(metaclass=FooOrbar):
foo = 42
v = Valid()
class Invalid(metaclass=FooOrbar):
foo =41
# 以上实现存在一个问题,他的子类并不会继承该功能,原因是元类直接检查attrs属性,但这只包含所声明的类属性集,
# 他并不知道继承自基类的属性
# class AlsoValid(Valid):
# pass
# 改进如下
class FooOrBarUpdate(type):
def __new__(cls, name,bases,attrs):
"""实例化,从基类中获取了所有的属性"""
answer = super(FooOrBarUpdate, cls).__new__(cls,name,bases,attrs)
if hasattr(answer,'foo') and hasattr(answer,'bar'):
raise TypeError('Class %s cannot contain both foo and bar'%name)
if not hasattr(answer,'foo') and not hasattr(answer,'bar'):
raise TypeError('Class %s must provide either foo or bar' % name)
return answer
# 3.非继承性
class Meta1(type):
def __new__(cls, name,bases,attrs):
if attrs.get('abstract',False):
return super(Meta1,cls).__new__(cls,name,bases,attrs)
class SubClass(metaclass=Meta1):
abstract = False
# 以上元类定义存在一个问题,任何子类都需要显示的声明自己并不是抽象类
# 改进如下 :
class MetaUpdate1(type):
def __new__(cls, name,bases,attrs):
if attrs.pop('abstract',False):
return super(MetaUpdate1, cls).__new__(cls,name,bases,attrs)
#meta-coding***************************************************************
class Logged(type):
""""a meta class that cause classes that it creates to log their function calls"""
def __new__(cls, name,bases,attrs):
for k,v in attrs.items():
if callable(v):
attrs[k] = cls.log_call(v)
return super(Logged, cls).__new__(cls,name,bases,attrs)
@staticmethod
def log_call(v):
def inner(*args,**kwargs):
try:
response = v(*args,**kwargs)
print('%s函数被调用,参数为%s,字典关键字为:%s.'%(v.__name__,args,kwargs))
return response
except Exception as e:
print('%s函数被调用,抛出异常:%s'%(v.__name__,e))
raise e
return inner
class MyClass(metaclass=Logged):
def foo(self):
pass
def bar(self):
raise TypeError('oh,noes')
obj = MyClass()
obj.foo()
obj.bar()