30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property
Posted 孤寒者
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property相关的知识,希望对你有一定的参考价值。
目录:
每篇前言:
🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者
- 🔥🔥本文已收录于Python全栈系列专栏:《Python全栈基础教程》
- 🔥🔥热门专栏推荐:《Django框架从入门到实战》、《爬虫从入门到精通系列教程》、《爬虫高级》、《前端系列教程》、《tornado一条龙+一个完整版项目》。
- 📝📝本专栏面向广大程序猿,为的是大家都做到Python从入门到精通,同时穿插有很多很多习题,巩固学习。
- 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!
Python面向对象(三)
1.1 类方法和静态方法
1.1.1 类方法
- 是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以’cls’作为第一个参数的名字,就最好用’cls’了),能够通过实例对象和类对象去访问。
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
p = People()
print(p.getCountry()) #可以用过实例对象引用
print(People.getCountry()) #可以通过类对象引用
- 类方法还有一个用途就是可以对类属性进行修改:
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
class People:
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
print(p.getCountry()) #可以用过实例对象引用
print(People.getCountry()) #可以通过类对象引用
p.setCountry('japan')
print(p.getCountry())
print(People.getCountry())
- 结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变。
1.1.2 静态方法
需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数。
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
class People:
country = 'china'
# 静态方法
@staticmethod
def getCountry():
return People.country
print(People.getCountry())
1.1.3 总结
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法的第一个参数是类对象cls,那么通过cls引用的必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也有可能是实例属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用
2.1 动态绑定与限制
2.1.1 动态绑定属性
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
class Student(object):
pass
s = Student()
s.name = 'Michael' # 动态给实例绑定一个属性
def set_age(self, age): # 定义一个函数作为实例方法
self.age = age
from types import MethodType
s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
s.set_age(25) # 调用实例方法
print(s.age) # 测试结果
但是,给一个实例绑定的方法,对另一个实例是不起作用的:
s2 = Student() # 创建新的实例
s2.set_age(25)
Traceback (most recent call last):
File "D:/******/test.py", line 17, in <module>
s2.set_age(25)
AttributeError: 'Student' object has no attribute 'set_age'
为了给所有实例都绑定方法,可以给class绑定方法:
def set_score(self, score):
self.score = score
Student.set_score = MethodType(set_score, Student)
给class绑定方法后,所有实例均可调用:
s.set_score(100)
print(s.score)
s2 = Student()
s2.set_score(99)
print(s2.score)
通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。
2.1.2 __slots__
限制绑定
- 如果我们想要限制class的属性,比如只允许对Student实例添加name和age属性。
- 为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的
__slots__
变量,来限制该class能添加的属性:
class Student(object):
__slots__ = ('name', 'age')
- 然后,我们就试试:
s = Student() # 创建新的实例
s.name = 'xiaoming' # 绑定属性'name'
s.age = 25 # 绑定属性'age'
s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'
- 由于’score’没有被放到
__slots__
中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。 - 使用
__slots__
要注意,__slots__
定义的属性仅对当前类起作用,对继承的子类是不起作用的:
除非在子类中也定义__slots__
,这样,子类允许定义的属性就是自身的__slots__
加上父类的__slots__
。
3.1 使用@property将方法变成属性调用
语法:
class property([fget[, fset[, fdel[, doc]]]])
参数:
- fget – 获取属性值的函数
- fset – 设置属性值的函数
- fdel – 删除属性值函数
- doc – 属性描述信息
返回新式类属性。
将 property 函数用作装饰器可以很方便的创建只读属性:
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
class Parrot(object):
def __init__(self):
self._voltage = 100000
@property
def voltage(self):
"""Get the current voltage."""
return self._voltage
- 上面的代码将 voltage() 方法转化成同名只读属性的 getter 方法。
- property 的 getter,setter 和 deleter 方法同样可以用作装饰器:
# -*- coding: utf-8 -*-
"""
__author__ = 小小明-代码实体
"""
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
3.2 mro算法
- mro顺序/算法,目的是保证程序能够按序执行。
mro顺序的作用:
- 保证所有的类在用(构造)他的时候只被用(构造)一次!
保证多继承的时候,每个类只出现一次。
super().__init__()
相当于使用了mro。
前面说要讲,但是在基础阶段如果深入讲的话,我怕大家一时接受不了,所以就先这样浅显有个认识即可!有机会我会细讲。
以上是关于30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property的主要内容,如果未能解决你的问题,请参考以下文章
30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property
Scala核心编程_第08章 面向对象编程(中级补充)--java动态绑定与静态绑定