标签:instance 存储 stand 使用 attr lse required == fir
classmethod 类方法
python的类方法是通过@classmethod装饰器实现的
类方法和普通的方法的区别是
类方法只能访问类变量,不能访问实例变量
class Dog(object):
def __init__(self, name):
self.name = name
@classmethod
def eat(self):
print("%s is eating" % self.name)
d = Dog("Mjj")
d.eat()
可以看到我调用Dog里面的eat方法,显示报错
AttributeError: type object 'Dog' has no attribute 'name'
果然,加上了这个类方法之后就没有办法访问实例变量(name)
但是她说可以访问类的变量,我们来定义一下
class Dog(object):
name = "我是类变量"
def __init__(self, name):
self.name = name
@classmethod
def eat(self):
print("%s is eating" % self.name)
d = Dog("Mjj")
d.eat()
执行结果如下:
我是类变量 is eating
熬 就可以看出来,使用了类变量之后
真的就只能调用类变量,而无法调用实例变量
但是为什么只能调用类变量不能调用实例变量呢?
我们打印一下self看一下传过来的是什么
class Dog(object):
name = "我是类变量"
def __init__(self, name):
self.name = name
@classmethod
def eat(self):
print(self)
print("%s is eating" % self.name)
d = Dog("Mjj")
d.eat()
<class '__main__.Dog'>
我是类变量 is eating
可以看到,这个传进来的是个类的本身
而不是实例的对象
所以当然就无法调用实例的属性了呀!
而且你也发现了,当你先@classmethod
再进行方法的定义的时候
你的括号里自动补充的不是self而是cls
那到底有什么用呢?
我在别人写的代码上有的时候会看到
但是在我自己进行开发的时候,基本上没用到
但是还是要给你举个例子,让你看看作用
现有一个Student类, 每生成一个Student实例,学生总数就自动+1
class Student(object):
stu_num = 0 # 学员计数需存在类变量里,不能存在每个实例里,因为每个实例的内存是独立的,每实例化一次,数据就会被重置一次,不会累加
def __init__(self, name):
self.name = name
self.stu_num += 1
print("total student num:", self.stu_num)
s1 = Student("张1")
s2 = Student("张2")
s3 = Student("张3")
s4 = Student("张4")
执行结果如下
total student num: 1
total student num: 1
total student num: 1
total student num: 1
为何每次都是1呢? 不应该累加么?
self.stu_num += 1
相当于对每个实例进行了一次赋值, 因为self代表实例本身
self.stu_num += 1 相当于s1.stu_num =1 , s2.stu_num = 1 …
把这句代码改成如下就可以:
class Student(object):
stu_num = 0 # 学员计数需存在类变量里,不能存在每个实例里,因为每个实例的内存是独立的,每实例化一次,数据就会被重置一次,不会累加
def __init__(self, name):
self.name = name
Student.stu_num += 1 # 直接用类名调用
print("total student num:", self.stu_num)
s1 = Student("张1")
s2 = Student("张2")
s3 = Student("张3")
s4 = Student("张4")
由于stu_num是每增加一个学员才加1的,不应该允许直接Student.stu_num+=1,不安全
可以封装成私有变量,再通过类方法调用并计数
class Student(object):
__stu_num = 0 # 学员计数需存在类变量里,不能存在每个实例里
def __init__(self, name):
self.name = name
self.add_stu_num() # 相当于Student.add_stu_num() 初始化学员时调用
@classmethod
def add_stu_num(cls): # 注意这里调用时传进来的其实是类本身,不是实例本身,所以参数名一般改为cls
cls.__stu_num += 1
print("total student num:", cls.__stu_num)
s1 = Student("张1")
s2 = Student("张2")
s3 = Student("张3")
s4 = Student("张4")
但是有的同学说!
Student.add_stu_num()
也是可以调的,你这样写是为了防止作弊
我这也能作弊啊!
你说的没错!
那么我们如何才能真的判断是不是真的要执行这句话?
关键点是不是在于我是否真的产生了一个类对象
所以,在执行之前就要有个验证
def __init__(self, name):
self.name = name
self.add_stu_num(self)
def add_stu_num(cls,obj):
if obj.name:
cls.__stu_num += 1
print("total student num:", cls.__stu_num)
这里我们用了obj
obj stands for self instance
这里的obj就是实例的意思
那经过这个操作之后,再进行“作弊操作”,就不行了!
staticmethod 静态方法
类方法不能访问实例变量,只能访问类变量是吧
静态方法更狠!
不仅实例变量,连类变量都不能访问!
!!!!!!!!!!!!!!!!!!!
@staticmethod装饰器即可把其装饰的方法变为一个静态方法
什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用
并且在方法里可以通过self.调用实例变量或类变量
但静态方法是不可以访问实例变量或类变量的
一个不能访问实例变量和类变量的方法
其实相当于跟类本身已经没什么关系了
它与类唯一的关联就是需要通过类名来调用这个方法
class Student(object):
role = "stu"
def __init__(self, name):
self.name = name
@staticmethod
def fly(self):
print("%s is flying..." % self.name)
s = Student("hah")
s.fly()
TypeError: fly() missing 1 required positional argument: 'self'
可以看到,并没有在调用fly方法的时候,默认添加进去一个参数
而是报了一个缺少一个参数的错误,一个实例对象
而当我把实例对象传进去,就没有问题了
s = Student("hah")
s.fly(s)
hah is flying...
其实你也就看出来了
这个装饰器,将fly方法,和Student类的关系隔离了
就算你在我的类下,你也不能调用我的方法
不常用
property 属性方法
属性方法的作用就是通过@property把一个方法变成一个静态属性
class Student(object):
stu_num = 0
def __init__(self, name):
self.name = name
@property
def fly(self):
print("%s is flying..." % self.name)
s = Student("haha")
s.fly()
直接这么调用会给你返回一个错误:
TypeError: 'NoneType' object is not callable
因为此时fly已经从方法变成属性了
而不再是一个方法了
那么怎么调用属性呢?
实例.属性 是吧
s.fly
执行出来就是这种效果
haha is flying...
理解起来很简单
那么到底有什么用呢?
如果我想要一个静态变量
我直接定义就好了
为什么要这么做呢?
首先,定义一个静态变量可以,但是只是个变量
他除了存储数据,没有别的卵用
但是通过装饰器@property是可以把方法变成静态的
而方法是可以做事情(调用)的
那在现实场景,有什么用呢?
比如我们要找火车票
是不是会先给服务器发信息
然后返回状态,最后打印啊
那么问题就来了
你在查询票的时候,你会关注他到底是怎么拿到数据的吗?
不会吧,而是会更多的关注票的信息
那你在获得票的信息的时候是不是想查询的是票的属性
而不是怎么获得的票!
那我们就可以模拟的写一下!
class Train(object):
def __init__(self, name):
self.train_name = name
def checking_status(self):
print("connecting trainline company api...... ")
print("checking train %s status " % self.train_name)
return 1
@property
def train_status(self):
status = self.checking_status()
if status == 0:
print("train got canceled...")
elif status == 1:
print("train is arrived...")
elif status == 2:
print("train has departured already...")
else:
print("cannot confirm the train status...,please check later")
f = Train("k470")
f.train_status
这样,用户在使用的时候就直接查询了票的属性
骚操作来了奥!既然他是个静态属性,是不是也是属性
那我能不能修改呢?
f.train_status = 0
AttributeError: can't set attribute
┗|`O′|┛ 嗷~~,会报错!
其实也能理解
你只是看上去是在查看属性
但是实际上,你还是在使用调用方法
所以不能修改也是合情合理
但是毕竟是个属性,如果用户提出修改的要求也无可厚非
对吧,你给我个属性,然后你说不能改?
说不过去吧!
所以这种问题怎么处理呢?
class Train(object):
def __init__(self, name):
self.train_name = name
def checking_status(self):
print("connecting airline company api...... ")
print("checking train %s status " % self.train_name)
return 1
@property
def train_status(self):
status = self.checking_status()
if status == 0:
print("train got canceled...")
elif status == 1:
print("train is arrived...")
elif status == 2:
print("train has departured already...")
else:
print("cannot confirm the train status...,please check later")
@train_status.setter
def train_status(self, status):
print("changing... ...", status)
f = Train("k470")
f.train_status = 0
在下面再写一个同名的函数,然后在上面加一个装饰器
名字是这个同名的函数加上.setter方法
同时要把你要修改的参数传进去(status)
changing... ... 0
那到底是不是真的修改了呢?
我们可以设置一个变量来接收
然后打印看看
@train_status.setter
def train_status(self, status):
print("changing... ...", status)
self.status = status
f = Train("k470")
f.train_status = 0
print(f.status)
打印了一下,澳!确实是有所改变
那我们能删除嘛?
del f.train_status
可以看到,报错了是吧
那我就想删除怎么办呢?
一样的!
在下面再写一个同名的函数,然后在上面加一个装饰器
名字是这个同名的函数加上.deleter方法
所以到此为止,我们知道了如何将方法变成一个静态的变量
并对这个静态的方法进行操作!
标签:instance 存储 stand 使用 attr lse required == fir
原文地址:https://www.cnblogs.com/jevious/p/11258926.html