类用来规范对象的属性和行为,类是对象产生的“生产指标书”,对象是根据类的指标下的产物
_ init_(self):函数中的self是一个空对象,等到init函数执行完成后,将这个self对象进行初始化,然后返回回去给其他的变量进行绑定。
_ del_(self):析构函数不需要传递任何参数,用来清理除对象以外的外部资源(如打开的文件)
一切皆对象,包括我们自己写的类,也是一个对象
一、类变量(c++中为静态成员变量)
上一篇文章中提到的__dict__ 以及__class__属性都是属于示例/对象的属性
什么是类变量:
类变量是类的属性,属于类,不属于此类创建的实例
说明:
为变量,可以通过该类直接访问
类变量可以通过此类的实例直接访问
类变量可以通过此类的对象 __class__属性间接访问
类变量通常来统计所有对象信息
(实际上c++中对象的属性封装在类中,直接定义好,而python是在初始化函数中才定义好的)
(而python中的类变量,又和中得静态变量类似)
示例:说明类变量的使用
class Human:
count = 0 #类变量,记录生成了多少个对象
print(Human.count)
h1 = Human()
print(h1.count) #通过对象来访问
Human.count = 1 #修改绑定关系,将类的变量count改为2
h1.count = 2 # 这是给h1对象中创建这个属性
print(Human.count)
#如果对象想修改类变量的值,只能通过__class__来修改
h1.__class__.count = 9
print(Human.count)
执行结果:
0
0
1
9
示例:类变量用在init函数中
class Human:
count = 0 #类变量,记录生成了多少个对象
def __init__(self,n):
self.name = n
# count + =1 这样不可以
#Human.count +=1 这样可以
self.__class__.count += 1 #每次生成一个对象 count+1
def __del__(self):
self.__class__.count -= 1 #每次销毁一个对象 count-1
print("当前的对象个数为: ",Human.count)
h1 = Human("张飞")
h2 = Human("李白")
print("当前的对象个数为: ",Human.count)
del h2
print("当前的对象个数为: ",Human.count)
执行结果:
当前的对象个数为: 0
当前的对象个数为: 2
当前的对象个数为: 1
二:类的__slots__属性
作用:
限定一个类创建实例只能有固定的属性(实例变量)
说明:
__slots__属性是一个列表,列表的值是字符串
含有__slots__属性的类所创建的对象没有__dict__字典
示例:__slots__属性来限定对象的属性,不允许私自修改种类和个数
class Student:
def __init__(self,n,a):
self.name = n
self.age = a
s1 =Student("小张",10)
s1.Age = 20 #可以吗 可以
#有时我们希望我们的对象只有name和age属性,不希望有其他的属性
#可以在定义类时写成下面的格式
class Student:
__slots__ = ['name','age']
#告诉解释执行器,我这个类实例的对象只有这两个属性,如果添加,会报错
def __init__(self,n,a):
self.name = n
self.age = a
我们在类中添加上对应__slots__属性后,再来看代码的执行
s1 =Student("小张",10)
s1.score= 20
执行结果:
AttributeError: 'Student' object has no attribute 'score'
加上__slots__后该类产生的对象没有__dict__属性:
s1 =Student("小张",10)
print(s1.__dict__)
执行结果:
AttributeError: 'Student' object has no attribute '__dict__'
三、类方法 @classmethod
类方法是操作类的方法,类方法属于类,不属于该类创建的对象
(对象的方法是描述对象的行为的,实际上我们定义的类也是个对象,也有自己的方法)
(对象的方法用来一般用来操作对象的属性(变量),类方法同样一般用来操作类的变量)
说明:
类方法需要使用@classmethod装饰器定义
类方法的第一个参数用来绑定类,约定写为cls
类和对象实例都可以调用类方法
类方法不能访问此类创建的对象的属性
示例:
class A:
v = 0
@classmethod
def get_v(cls): #调用时传入的是一个类cls,而不是类的对象
return cls.v
@classmethod
def set_v(cls,val): #等价于A.v = val
cls.v = val
print(A.get_v()) #此时cls绑定的是A
a = A()
a.set_v(100)
# 类方法实例也可以调,此时cls绑定的是a.__class__
print(a.get_v())
执行结果:
0
100
四、静态方法 @staticmethod
静态方法是定义在类的内部函数,此函数的作用域是类的内部
说明:
静态方法需要使用@static装饰器定义
静态方法和普通函数定义的相同,不需要传入cls或者self
静态方法只能凭借该类变量和实例变量
静态方法不能访问类变量和实例变量
示例:
class A:
@staticmethod
def myadd(a,b):
return a+b
#静态方法不传入cls或者self,自然就找不到对象或者类的属性
#这也是静态方法不能访问类或者对象属性的原因
print(A.myadd(100,200))
a = A()
print(a.myadd(7,9))
#由于该函数是定义在类内的,所以调用必须依赖类或者对象
#否则没法调用
#其实这也是面向对象的思想,将这种看似与类无关的函数封装在类内
#myadd(100,200) 无法调用,解释执行器会找不到这个函数
执行结果:
300
16