vps网站能打开,网站建设标签,seo黑帽排名,前端网站开发一个月多少钱1 python类对象与实例对象python中一切皆对象(广义上的对象)#xff0c;类也不例外#xff0c;我们可以称类为类对象。python中内建函数type()可以返回对象的类型#xff0c;例如type(int)会得到返回值#xff0c;而int为类型工厂函数#xff0c;是内置的类对象。如果对自…1 python类对象与实例对象python中一切皆对象(广义上的对象)类也不例外我们可以称类为类对象。python中内建函数type()可以返回对象的类型例如type(int)会得到返回值而int为类型工厂函数是内置的类对象。如果对自定义的类使用type()也会返回相同的值。从上述我们可以总结出python中type为一般类对象的类(除非子类化type用type子类创建类对象)即type类可以实例化得到类对象再由类对象实例化得到实例对象。创建类的类被称为元类1.1 类属性实例属性1.1.1 类属性类属性是一个类对象的数据或函数元素类属性包括数据属性和方法。数据属性 是仅属于类的变量与任何实例无关这与C和Java中静态成员变量相似。方法 是定义在类中的函数根据用法可以分为绑定方法与非绑定方法。绑定方法必须实例化后才能调用需要与实例绑定非绑定方法则可以分为静态方法和类方法可以使用装饰器staticmethod和classmethod实现。虽然绑定方法需要实例化后才能调用但其定义在类中因此其也属于类的属性。class P():version 1.0 #类的静态数据classmethoddef show(cls): #类方法print(cls.version)def __init__(self, name, address): #绑定方法self代表实例self.name nameself.address addressdef display(self):print(self.name)print(self.address)def __call__(self):print(self.name)def fn():print(hello,python)if __name__ __main__:p P(jay,american)p1 P(h,china)p1.fn fnprint(P.__dict__)print(p1.__dict__)以上是创建类对象的一个例子__dict__为对象的特殊属性其值为对象属性构成的字典(并非所有类或实例都有该属性若定义了__slots__属性则会取代__dict__属性)运行结果如下{__module__: __main__, version: 1.0,show: , __init__: , display: , __call__: , __dict__: , __weakref__: , __doc__: None}{name: h, address: china, fn: }运行结果同时也验证了上述说法类中定义的绑定方法__init__, display, __call__和非绑定方法show都是属于类的属性而fn,name,address则属于实例属性。1.1.2 实例属性实例属性是只属于实例对象的方法和数据属性。不同于静态语言python能动态地创建实例属性上述代码中的fn即为动态创建的实例属性。但这样特性的缺陷是如果实例属性在条件语句中创建若该条件语句并未执行该属性也就不存在而后面的代码试着访问这些属性就会发生错误。解决办法是避免中途创建实例属性尽量在__init__方法中初始化实例属性。1.1.3 类属性VS实例属性类属性也能通过实例访问但前提是该实例中没有同名的属性。任何对实例属性的赋值都会新建一个实例属性并对其赋值但如果类属性中存在同名的属性则不会对类属性产生影响若要改变类属性需要使用类名而不是实例名。class P():version 1p1 P()p1.version1p1.version 2p1.version2P.version1P.version 2P.version21.2 类的特殊方法(魔术方法)__init__初始化方法属于类的绑定方法第一个参数必须为self(代表实例对象)且无返回值在__new__返回实例对象后才能调用。__new__真正的构造方法用于创建实例对象属于静态方法第一个参数为cls(代表类对象)其返回值为实例对象。__call__将对象设置为可调用对象(可以向函数一样用()调用)元类type中实现了该函数因此类对象为可调用对象实例化时就是通过调用类来创建实例对象的覆盖时需要调用父类方法即super().__call__()关键知识覆盖上述特殊函数时需要特别注意元类中自定义__call__(self, *args, **kwargs)类对象中若自定义__init__(self, *args, **kwargs) 则自定义__new__(cls, *args, **kwargs)原因如下p1 P(*args, **kwargs)执行顺序P.__call__(*args, **kwargs):super().__call__(*args, **kwargs)goto↓p1 object().__new__(P)p1.__init__(*args, **kwargs)return p12 Metaclass元类2.1 自定义元类元类是用来创建其他的类它的实例就是其他的类。执行类定义时解释器会先寻找类属性__metaclass__如果此属性中未定义则向上查找其父类中的__metaclass__type的__init__函数有三个位置参数分别为类名称父类名称元祖类属性字典可直接使用type()快速创建类对象People type(People,(object,),dict(show fn, setage fn1, age None))也可子类化type类后创建元类再创建类对象from time import ctimeclass MetaC(type):def __init__(self, *args):super().__init__(*args)print(调用类的init)def __call__(self, *args, **kwargs):print(调用类的call)_instance super().__call__(*args, **kwargs)print(call return %s %_instance)return _instanceclass Foo(metaclassMetaC):# __metaclass__ MetaCdef __init__(self, versionNone):print(调用对象的init)def __new__(cls, *args, **kwargs):print(调用对象的new)_instance super().__new__(cls)print(new return %s %_instance)return _instancefoo Foo(hello)运行结果调用类的init调用类的call调用对象的newnew return __main__.foo object at调用对象的initcall return __main__.foo object at2.2 单例模式的实现下面是几种单例模式的实现方法有些会用到上述的元类知识。2.2.1 装饰器实现单例import weakrefdef single_obj(cls):#实例缓存为弱引用实例不被使用时会释放该实例_spam_cache weakref.WeakValueDictionary()wraps(cls)def wrapper(*args, **kwargs):if cls not in _spam_cache :_instance cls(*args, **kwargs)_spam_cache [cls] _instancereturn _instanceelse:return _spam_cache [cls]return wrappersingle_objclass A():def __init__(self, version):self.version versionprint(self.version)a1 A(1.3)a2 A(1.2)print(a1 id:,id(a1))print(a2 id:,id(a2))2.2.2 利用元类类的__call__方法实现单例class Singleton(type):def __init__(self, *args, **kwargs):self._instance Nonesuper().__init__(*args, **kwargs)def __call__(self, *args, **kwargs):if self._instance is None:self._instance super().__call__(*args, **kwargs)return self._instanceelse:return self._instanceclass B(metaclassSingleton):def __init__(self, name):self.name nameprint(name)b1 B(what)b2 B(hell)print(b2.name)print(b1 id:,id(b1))print(b2 id:,id(b2))2.2.3 通过__new__实现单例(此方法不可行)class C(object):_instance Nonedef __init__(self, name):self.name nameprint(name)def __new__(cls, *args, **kwargs):if cls._instance is None:cls._instance super().__new__(cls)return cls._instancec1 C(dsfsfd)c2 C(java)print(c1 id:,id(c1))print(c2 id:,id(c2))若采用上述方法无论类是否实例化__init__都会被调用实例对象会被修改