在前面的例子中我们接触到的就是实例属性(实例对象属性),顾名思义,类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。对于公有的类属性,可以通过类或者实例对象访问 实例属性只能通过对象来调用,类不能调用
- class People(object):
- name="Tom" #共有属性
- __age=12 #私有属性
- p=People()
-
- print(p.name) #正确
- print(People.name) #正确
- print(p.__age) #错误 不能在类外通过实例对象访问私有的类属性
- print(People.__age) #错误 不能在类外通过类对象访问私有的类属性
可以通过类或者实例对象调用
- class People(object):
- address="山东" #类属性
- def __init__(self):
- self.name="xiaowang"
- self.age=20
- p=People()
- p.age=12 #实例属性
- print(p.address) #正确
- print(p.age) #正确
- print(p.name) #正确
- print(People.address) #正确
- print(People.name) #错误
- print(People.age) #错误
可以通过实例化对象调用,类不能调用
- class People(object):
- country="china" #类属性
- print(People.country)
- p=People()
- print(p.country)
- p.country="japan" #实例属性
- print(p.country) #实例属性会屏蔽掉同名的类属性
- print(People.country)
- del p.country #删除实例属性
- print(p.country)
总结:对象修改类属性,只对本对象有效果,对别的 对象没有影响
是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,(当然可以用其他名称的变量作为其第一个参数),当时大部分人都习惯以"cls"作为第一个参数的名字,就最好用"cls"了),能够通过实例对象和类对象去访问.
- class People(object):
- age=18 #类属性
- @classmethod #用classmethod进行修饰
- def get_country(cls):
- return cls.age
- p=People() #实例化
- print(p.get_country()) #可以用实例对象引用
- print(People.get_country()) #可以通过类对象引用
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!类方法还有一个用途就是可以对类属性进行修改
- class People(object):
- age=18 #类属性
- @classmethod #类方法 @用classmethod来修饰
- def get_country(cls):
- return cls.age
- @classmethod
- def set_country(cls,age):
- cls.age=age
- p=People()
- print(p.get_country()) #可以通过实例对象访问
- print(People.get_country()) #可以通过类访问
- p.set_country(23)
- print(p.get_country())
- print(People.get_country())
- p1=People()
- print(p1.get_country())
结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变(全部改变)
需要通过修饰器@staticmethod来进行修饰.静态方法不需要多定义参数,可以通过对象和类来访问.
- class People(object):
- country="china"
- @staticmethod #静态方法
- def get_country():
- return People.country
- p=People() #实例化对象
- print(p.get_country()) #通过对象访问静态方法
- print(People.get_country()) #通过类访问静态方法
静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类实例对象来引用,调用静态方法可以通过对象或者类调用
实例方法中的第一个参数是self,只能通过对象来访问
实例方法中需要self参数,因此调用实例方法只能通过实例对象调用 也可以通过类调用但是一般不这样用
- class People(object):
- def selfmethod(self):
- print("我就是实例方法")
- p=People()
- p.selfmethod() #通过对象访问
- #People.selfmethod() 会报错
总结:
类方法使用@classmethod装饰,第一个参数为类(cls),调用可以通过类的实例或者类本身来调用.
实例方法定义时第一个参数为类的第一个实例(self),调用是必须通过实例调用
静态方法使用@staticmethod装饰,调用时可以使用类的实例或者类本身来调用.
- class A(object):
- def __init__(self):
- print("这是__init__方法")
- def __new__(cls, *args, **kwargs):
- print("这是new方法")
- return object.__new__(cls)
- a=A()
注意点:
- class A(object):
- def __init__(self):
- print("*"*40)
- print(self)
- print("这是__init__方法")
- def __new__(cls, *args, **kwargs):
- print(id(cls))
- print("这是new方法")
- ret=object.__new__(cls)
- print(ret)
- return ret
- a=A()
总结:
1). __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
2). __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
3). __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值
4). 我们可以将类比作制造商,__new__方法就是前期的原材料购买环节,__init__方法就是在有原材料的基础上,加工,初始化商品环节
单例模式:永远用一个对象的实例,避免新建太多实例浪费资源
实质:使用__new__方法新建类对象时先判断是否已经建立过,如果建立过就使用已有的对象
- class Foo(object):
- instance=None
- def __init__(self):
- self.name="alex"
- def __new__(cls, *args, **kwargs):
- if Foo.instance:
- return Foo.instance
- else:
- Foo.instance=object.__new__(cls)
- return Foo.instance
- obj1=Foo()
- obj2=Foo()
- print(obj1,obj2)
( ̄▽ ̄)~*------ ٩(๑❛ᴗ❛๑)۶谢谢阅读!!!!!!!!!!!!!