类属性:
针对类对象定义的属性 使用赋值语句在class关键字下可以定义类属性
当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到,当实例并没有该属性,所以会继续查找class的该属性
class fairy:
name='jing' #定义类属性
print(fairy.name)
xiannv=fairy()
print(xiannv.name)
jing
jing
千万不要对实例属性和类属性使用相同的名字,因为实例属性优先级高于类属性。相同名称的实例属性将屏蔽掉类属性
class fairy:
name='jing' #定义类属性
def __init__(self,x):
self.name=x
print(fairy.name)
xiannv=fairy('jj')
print(xiannv.name)
jing
jj
类方法:
针对类对象定义的方法 在类方法内部可以直接访问类属性或者调用其他的类方法
@classmethod
def 方法名称(cls): ##cls表示调用该方法的类本身
操作
class fairy:
name='jing' #定义类属性
@classmethod
def eat(cls):
print('%s want to eat meat' %(cls.name))
print(fairy.name)
fairy.eat()
jing
jing want to eat meat
———————练习———————
统计创建的玩具数量
class Toy(object):
# 使用赋值语句定义类属性,记录所有的玩具的数量
count = 0
def __init__(self,name):
self.name = name
# 让类属性 +1
Toy.count += 1
@classmethod
def show_toy_count(cls):
print('玩具对象的数量 %d' %(cls.count))
# 创建玩具对象
# toy1 = Toy('乐高')
# toy2 = Toy('泰迪熊')
# 调用类方法
Toy.show_toy_count()
静态方法
如果需要在类中定义一个方法,这个方法,既不需要访问实例属性也不需要调用实例方法;既不需要访问类属性也不需要调用类方法,这个时候就可以把这个方法封装成静态方法。使用@staticmethod关键字进行设置
class Cat(object):
@staticmethod
def call():
print('喵')
# 通过 类名. 调用静态方法
Cat.call()
# 不需要创建对象 直接就可以调用
hk=Cat()
hk.call()
喵
喵
私有属性和私有方法
私有属性:前面带两个下划线表示对变量进行私有化,私有化之后的属性属于类内部的属性,可以在内部进行访问,外部无法随便进行访问或者修改。
私有方法:方法名称前面带两个下划线表示方法私有化,可以在内部进行调用,不能使用实例在外部调用私有化方法。
定义属性或方法
在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
class Student(object):
def __init__(self,name,score):
# 前面带两个下划线表示对变量进行私有化,
# 外部不能随便的访问和更改
self.__name = name
self.__score = score
def get_grand(self):
print('my name is %s,my '
'grade is %d' %(self.__name,self.__score))
def get_name(self):
return self.__name
def get_score(self):
return self.__score
def set_name(self,name):
if isinstance(name,str):
self.__name = name
else:
raise ValueError('请输入正确的名字')
def set_score(self,score):
if isinstance(score,int):
self.__score = score
else:
raise ValueError('请输入正确的成绩')
tom = Student('Tom',89)
# print(tom.name)
# print(tom.score)
tom.get_grand()
# print(tom._Student__name)
#tom.__name = 'new name' # 这样做只是给实例添加了__name的属性,并不是
# 修改私有属性变量
tom.set_name(321321)
tom.set_score(90)
print(tom.get_name())
print(tom.get_score())
设计模式——单例
设计模式:
设计模式是前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对某一特定问题的成熟解决方案,使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码可靠性
单例设计模式:
目的:
让类创建对象,在系统中只有唯一的一个实例,每一次执行类名()返回的对象,内存地址是相同的
使用__new__(cls)方法实现单例设计模式:
我们用 类名. 的方式创建对象的时候,python解释器会帮我们做两件事情,
1.为对象分配空间
__new__是一个由object基类提供的内置的静态方法,主要有两个作用:负责给对象分配空间,并返回对象的引用给初始化方法
2.对象初始化
init(初始化方法)负责给对象初始化.
解释器获得对象的引用后,将引用作为第一个参数,传递给__init__方法
重点
在Python3中,class定义的时候,如果不显式的写继承object,也是会默认自动继承object的,所以也会有__new__(cls)
也就是说在使用类名创建对象的时候,会自动的调用object基类中的__new__(cls)方法生成对象并返回对象的引用。
我们可以在类中对__new__(cls)方法进行重写,使其达到效果是:如果是第一次使用该类创建对象,那就在内存中为对象分配内存空间,并且返回对象的引用,如果已经创建过对象,那就不在重新分配内存空间,直接返回上次创建好的内存空间即可。
所以需要一个类属性来记录是否已经创建过对象,以及存储第一次创建对象时分配的内存地址空间。
重写__new__方法的代码非常固定:
继承自父类方法
返回父类方法调用_new__方法的结果
重写__new__方法一定要return object.new(cls)
否则python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
单例设计模式 示例:
class MusicPlayer(object):
instance = None
def __new__(cls, *args, **kwargs):
print('创建对象 分配空间')
# 1.创建对象的时候,new方法会被自动调用
#instance = object.__new__(cls)
#return instance #返回的是对象的引用
# 判断类属性是否是空对象
if cls.instance is None:
# 调用父类方法 为第一个对象分配空间
cls.instance = object.__new__(cls)
return cls.instance
player1 = MusicPlayer()
player2 = MusicPlayer()
player3 = MusicPlayer()
print(player1)
print(player2)
print(player3)
创建对象 分配空间
创建对象 分配空间
创建对象 分配空间
<__main__.MusicPlayer object at 0x7fc6e16e5320>
<__main__.MusicPlayer object at 0x7fc6e16e5320>
<__main__.MusicPlayer object at 0x7fc6e16e5320>