Python编程_Lesson016_类的高级用法
来源:互联网 发布:宝日龙梅 知乎 编辑:程序博客网 时间:2024/06/06 03:01
类的静态成员
类的静态属性
我们先来看一个例子:
class UserInfo(object): company = "PoEdu"user_info = UserInfo()user_info.company'PoEdu'UserInfo.company'PoEdu'
这个company是什么呢?更为奇怪的是我们可以直接拿着类名来访问company这个属性!
我们将这样的属性称为类的静态属性
静态属性是属于类的,而并不是属于类的某一个函数。
class UserInfo(object): company = "PoEdu"user_info = UserInfo()user_info.company'PoEdu'UserInfo.company'PoEdu'user_info_2 = UserInfo()user_info_2.company'PoEdu'user_info.company = "poedu"user_info.company'poedu'user_info_2.company'PoEdu'UserInfo.company'PoEdu'UserInfo.company = "poedu"user_info.company'poedu'user_info_2.company'poedu'UserInfo.company'poedu'UserInfo.company = "PoEdu"UserInfo.company'PoEdu'user_info.company'poedu'user_info_2.company'PoEdu'
这个例子说明了类的静态属性的以下几个特点:
- 每个对象中都会有一个静态属性
- 对象中的静态属性是可以被更改的,但是它对于其它对象以及类中的静态属性没有任何影响
- 类中的静态属性也是可以被更改的,但是它的更改就会影响所有的对象中的静态属性
- 当类中再次修改回来时,user_info对象自己修改过后的company静态属性就再也不会修改回来了(可以说已经失去了UserInfo类中的静态属性company了)
从上面可以看出,Python中的静态属性并不想其它语言中的静态属性定义的那么严格,静态属相属于类里面的一个属性,但是对象会拥有这个变量,实用类来修改这个属性的话,所有的对象中(自身修改过静态属性的对象除外)的这个属性都会发生改变,而对象中修改这个静态属性只是修改了对象本身的静态属性。
上面的特点我们可以从Python中的动态绑定可以看出来,实际上对象在给静态属性赋值的时候,已经把原来的静态属性给覆盖掉了。
对于类中的静态函数也是一样的,这里就不多说了,可以自己做实验看看效果!!!
这种动态既有优点,又有缺点。这里我们说一下如何避免这种缺点。
动态绑定的限制
我们可以使用‘slot()’函数来限制只允许动态绑定哪些属性。
demo_1.company = "PoEdu"class Demo(object): __slots__ = ("username", "password")demo_1 = Demo()demo_1.username = "root"demo_1.password = "root"demo_1.name = "admin"Traceback (most recent call last): File "<input>", line 1, in <module>AttributeError: 'Demo' object has no attribute 'name'
这样可以避免类中动态绑定带来的问题!
类的高级特性
像上一篇中我们使用setter和getter函数可以对隐藏的属性进行设置和访问,但是总是感觉还是没有那么的好用,我们能不能就可以隐藏属性,又可以直接使用(.)点来点出来呢?可以的!!!
‘@property特性’
这个特性是设置隐藏属性的访问
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance @property def username(self): return self.__username def print(self): print("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance))def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1.username) user_info_1.print()if __name__ == "__main__": main()
结果如下:
rootUser Name:root Password:root Salary:3000 Balance:1600
但是我们现在还不能给username赋值,不信的话可以试试,反正我是信了。
如果想要修改,我们还需要写一个函数:
这里写代码片
‘@property特性’
这个特性是设置隐藏属性的修改
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance @property def username(self): return self.__username @username.setter def username(self, username): self.__username = username def print(self): print("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance))def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1.username) user_info_1.username = "admin" print(user_info_1.username) user_info_1.print()if __name__ == "__main__": main()
结果如下:
rootadminUser Name:admin Password:root Salary:3000 Balance:1600
__str__()
特性
我们经常会看到这样的一种需求,使用print函数直接打印一个对象,而不是调用对象本身定义的print函数,我们这样该如何实现呢?
我们先直接打印一下看看
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance @property def username(self): return self.__username @username.setter def username(self, username): self.__username = username def print(self): print("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance))def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1)if __name__ == "__main__": main()
结果如下:
<__main__.UserInfo object at 0x00000232AED3E7B8>
这不是我们想要的结果!
因为print函数需要接收一个str对象,所以我们只需要实现__str__()
函数即可
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance def __str__(self): user_info = str.format("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance)) return user_info @property def username(self): return self.__username @username.setter def username(self, username): self.__username = username def print(self): print("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance))def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1) user_info_1.print()if __name__ == "__main__": main()
结果如下:
User Name:root Password:root Salary:3000 Balance:1600User Name:root Password:root Salary:3000 Balance:1600
打印结果一样!
__repr__()
上面的结果是我们使用print函数的时候打印的,我们知道print函数在调用我们对象的时候,会做一些转换,如果我们在调试状态下想输出对象信息该怎么办呢?先看一个简单的例子
class Demo(object): def __str__(self): return "Demo.__str__()"demo = Demo()print(demo)Demo.__str__()demo<Demo object at 0x000002C2EE72AF98>
说明在调试的时候,并没有一个强转的功能,我们需要__repr__()
函数来进行强转
class Demo(object): def __repr__(self): return "Demo.__str__"demo = Demo()print(demo)Demo.__str__demoDemo.__str__
此时无论使用print函数还是在控制台调试输出,都会直接打印对象的信息。
__iter__()和__next__()
实现对象的课迭代来进行遍历
import randomclass UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def __iter__(self): print("UserInfo.__iter__()") return self def __next__(self): print("UserInfo.__next__()") ret = random.randint(1, 10) self.__loop -= 1 if not self.__loop: raise StopIteration() return retdef main(): user_info_1 = UserInfo("root", "root", 3000, 1600) for i in user_info_1: print(i)if __name__ == "__main__": main()
结果如下:
UserInfo.__iter__()UserInfo.__next__()6UserInfo.__next__()3UserInfo.__next__()1UserInfo.__next__()10UserInfo.__next__()5UserInfo.__next__()8UserInfo.__next__()2UserInfo.__next__()8UserInfo.__next__()6UserInfo.__next__()
这样就和list有点儿相似了,我们可以利用这个特点依次来返回我们的每个属性,但是它和list还不一样,因为list还有切片、取下标等操作。
__getitem__()
函数实现取下标功能
如果我们想要实现取下标的功能,该怎么做呢?
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def __getitem__(self, item): return itemdef main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1[10])if __name__ == "__main__": main()
打印结果:
10
说明下标函数调用成功。
__getitem__()
函数实现切片功能
我们直接使用切片看看结果:
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def __getitem__(self, item): return itemdef main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1[10:100])if __name__ == "__main__": main()
打印结果如下:
slice(10, 100, None)
但是结果不对!
还是使用__getitem__()
函数进行切片,我们就需要做一些判断
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def __getitem__(self, item): if isinstance(item, int): return "int" elif isinstance(item, slice): return "slice"def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) print(user_info_1[1]) print(user_info_1[10:100])if __name__ == "__main__": main()
结果如下:
intslice
__call__()
函数
对象可以直接被当成函数来调用,此时就会调用__call__()
函数。
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def __call__(self): print("Demo.__call__()")def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) user_info_1()if __name__ == "__main__": main()
结果如下:
Demo.__call__()
这种用法非常适合敏捷开发,因为敏捷开发的需求是在不停地变化的。它可以在所有的方法之前加上一个功能(比如验证功能),我们不可能把我们写过的每一个方法加上一个验证的函数。
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def print(self): print("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance)) def __call__(self): print("Demo.__call__()")class CheckFoo(object): def __init__(self, foo): self.__foo = foo def __call__(self): print("check") self.__foo()def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) check_foo = CheckFoo(user_info_1.print) check_foo()if __name__ == "__main__": main()
打印结果:
checkUser Name:root Password:root Salary:3000 Balance:1600
这就是函数适配器的用法!
在stl中经常使用这个函数适配器!!!
__del__()
函数
我们称__del__()
为析构函数__init__()
为构造函数
class UserInfo(object): def __init__(self, username, password, salary, balance): self.__username = username self.__password = password self.__salary = salary self.__balance = balance self.__loop = 10 def print(self): print("User Name:%s Password:%s Salary:%d Balance:%d" % (self.__username, self.__password, self.__salary, self.__balance)) def __call__(self): print("Demo.__call__()") def __del__(self): print("UserInfo.__del__()")class CheckFoo(object): def __init__(self, foo): self.__foo = foo def __call__(self): print("check") self.__foo()def main(): user_info_1 = UserInfo("root", "root", 3000, 1600) check_foo = CheckFoo(user_info_1.print) check_foo()if __name__ == "__main__": main()
结果如下:
checkUser Name:root Password:root Salary:3000 Balance:1600UserInfo.__del__()
我们看到Python中有这么多好用的函数,但是又好像还缺少些什么,仔细一想,哦~原来是枚举!!!
实际上是有枚举类的。
枚举类
枚举类是需要导入的,方法如下from enum import Enum
。
我们可以直接使用枚举类
from enum import Enumdef main(): color = Enum("Color", ("red", "green", "blue")) print(color["red"])if __name__ == "__main__": main()
结果如下:
Color.red
我们也可以自己定义一个枚举类
from enum import Enum, unique#枚举类,unique是用来检测重复的,如果有重复的则编译不通过@uniqueclass Color(Enum): RED = 1 GREEN = 2 BLUE = 3 COLOR = "clr"def main(): color1 = Color("clr") print(color1) color2 = Color(2) print(color2)if __name__ == "__main__": main()
结果如下:
Color.COLORColor.GREEN
枚举可以将一些数值赋予一些意义,这对于通信将会有很大的帮助。
- Python编程_Lesson016_类的高级用法
- Python编程_Lesson016_类的高级特性_错误处理
- python的高级用法 -- namedtuple
- Python 函数的高级用法
- Python高级编程--元类
- python中urllib的高级用法
- python的一些高级用法积累
- Python爬虫Urllib2库的高级用法
- socket编程的一些高级用法
- Python编程_Lesson015_类的基础用法
- python requests 高级用法
- python requests 高级用法
- Python 高级用法
- 计划学习python的高级编程
- python的高级编程--之进程
- python高级编程推荐的好博客
- python with 语句的实例用法 & 高级用法:
- python高级编程 ------元类(1)
- 设计模式——模板方法模式( Template Method Pattern)
- 端口号调研、URG和PSH、及TCP的计时器
- eclipse报错Resource is out of sync with the file system的解决方法
- 逻辑学 随笔 (始于正方法而终于负方法)
- .NET后端处理带有"\"符号的数据
- Python编程_Lesson016_类的高级用法
- 链表翻转
- 刷题——通过前序中序遍历重建二叉树
- java 基础篇
- android的recovery,fastboot和bootloader
- BZOJ 3377 [Usaco2004 Open]The Cow Lineup 奶牛序列
- 百练_2719:陶陶摘苹果
- 进程间通讯——指针方式的内存读写
- 使用深度网络创造艺术:CAN, creative adversarial networks