快速了解Python的定制类
多重继承
class Student(man,oldman):
pass
可以继承多个父类,拥有他们的方法,如果有父类有相同的方法,哪个在前用哪个
定制类
看到类似__slots__这种形如 __xxx__的变量或函数名就要注意,这些在python中是有特殊用途的
我们已经知道了__slots__的用法,用__len__()方法我们也知道是为了能让class作用于len()函数
__str__
我们先定义一个Student类,打印一个实例
class Studentc():
def __init__(self,name):
self.__name = name
print(Studentc('cc'))
--> <__main__.Studentc object at 0x0000000000B48B00>
打印出来一坨不好看,我们定义一下__str__()方法,返回一个好看的字符串
class Studentc():
def __init__(self,name):
self.__name = name
def __str__(self):
return 'Studentc object (name : %s)'% self.__name
print(Studentc('cc')) # Studentc object (name : cc)
这里return 不用敲print
但是直接敲变量在shell下运行,打印出来的还是不好看
1
2
3
|
>>> s = Student( 'Michael' ) >>> s <__main__.Student object at 0x109afb310 > |
这是因为直接显示变量调用的不是__str__(),而是__repr__(),两者的区别就是__str__()返回用户看到的字符串,而__repr__返回程序开发者看到的字符串,也就是说__repr__()是为调试服务的
解决办法是再定义一个__repr__()。但是通常两个代码是一样的,可以偷懒
class Studentc():
def __init__(self,name):
self.__name = name
def __str__(self):
return 'Studentc object (name : %s)'% self.__name
__repr__ = __str__
__iter__
如果一个类想要被用于for in 循环,必须实现一个__iter__()方法,改方法返回一个迭代对象,然后就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环
class Fib():
def __init__(self):
self.__a,self.__b = 0,1
def __iter__(self):
return self
def __next__(self):
self.__a,self.__b = self.__b,self.__a + self.__b
if self.__a >1000:
raise StopIteration
else:
return self.__a
for x in Fib():
print(x)
__getitem__
Fib实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list使用还是不行比如取第五个元素
class Suv():
def __getitem__(self,n):
a,b = 0,1
for x in range(n):
a,b = b,a+b
return a
print(Suv()[3])
list还有切片功能,这里不能用,因为我们不知道传进来的是什么需要做一个判断
isinstance(n,slice) slice是切片的类型。还有负数等没有处理真想完全实现的话需要添加很多
__getattr__
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错
避免这种情况,除了可以加上一个score属性外,python还有另一个机智,那就是写一个__getattr__()方法,动态返回一个属性
class Su():
def __init__(self):
self.name = 'cc'
def __getattr__(self, item):
if item == 'score':
return '99'
print(Su().score)
当调用的属性不存在时,比如score,python会试图调用__getattr__(self,'score')来尝试获得属性,这样我们就有机会返回score的值
返回函数也是可以的
class Student():
def __init__(self):
self.name = 'cc'
def __getattr__(self, item):
if item == 'age':
return lambda :25
print(Student().age())
返回一个函数,调用的时候修改成Student().age()
注意,只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找
此外,如果没对未知的属性做处理,if判断输出的话。会返回None,要让class只响应特定的几个属性,我们就按照约定抛出AttributeError的错误
class Student():
def __init__(self):
self.name = 'cc'
def __getattr__(self, item):
if item == 'age':
return lambda :25
raise AttributeError('no have %s'%item)
print(Student().ac())
这实际上可以吧一个类的所有属性和方法调用全部动态化处理了,不需要任何特殊手段
这种完全动态调用的特性与什么实际作用呢?作用就是可以针对完全动态的情况作调用
举个例子
现在很多网站都搞rest api,比如新浪微博,豆瓣 调用api的url类似
http://api.server/user/friends
如果要写sdk,给诶给url对应的api写一个方法,那得累死,而且一旦api改动,sdk也要改
利用完全动态的__getaattr__我们可以写一个链式调用
class Chain():
def __init__(self,ab=""):
self._path =ab
def __getattr__(self, path):
print('self._path = %s ,path = %s'%(self._path,path))
return Chain('%s/%s' % (self._path,path))
def __str__(self):
return self._path
__reper__ = __str__
c = Chain().status.user.time.list
print(c)
1
2
3
4
5
|
self ._path = ,path = status self ._path = / status ,path = user self ._path = / status / user ,path = time self ._path = / status / user / time ,path = list / status / user / time / list |
属性都不存在,每一次都调用__getattr__方法,返回当前self._path + 属性名,并被_path获得,不断累加直到没有属性
打印返回self._path 的值
__call__
一个对象实例可以与自己的属性和方法,当我们调用实例方法时,我们会用instance.methond()来调用。能不能直接在实例本身上调用呢,在python答案是肯定的
任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用
class Students():
def __init__(self,name):
self.name = name
def __call__(self):
print('myname is %s'% self.name)
s1 = Students('s1')
s1()
__call__()还可以定义参数。对实例进行直接调用就好比对一个函数调用一样,所以你完全可以把对象看出函数,把函数看成对象,因为两者之间本来就没有什么根本的区别
如果你把对象看成函数,那么函数本身其实也可以在运行期间动态创建出来的,这么一来,我们就模糊了对象和函数的界限。
那么如何判断一个变量是对象还是函数呢?其实我们只需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象,比如函数和我们上面定义的__call__()的类实例
print(callable(Student))
print(callable([1,2,34]))
print(callable(None))
print(callable('str'))
快速了解Python的定制类的更多相关文章
- python基础——定制类
python基础——定制类 看到类似__slots__这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的. __slots__我们已经知道怎么用了,__len__()方 ...
- python中定制类
1.python中__str__和repr 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, ...
- Python——13定制类
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 【Python】[面向对象高级编程] 多成继承,定制类,使用枚举
1.多成继承 class SmallDog(Animal,Dog) pass MixIn就是一种常见的设计. 2.定制类类似__slots__这种形如 __xxx__ 的变量或者函数名,在python ...
- python 定制类
看到类似__slots__这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的. __slots__我们已经知道怎么用了,__len__()方法我们也知道是为了能让cla ...
- python学习第十七天 --定制类
何为定制类? Python的class允许定义许多特殊方法,可以让我们非常方便地生成特定的类.在类中应用或者重写python的特殊方法,得到的类,就是定制类. 大家都知道print的用法.见下面例子 ...
- Python面向对象高级编程-__slots__、定制类,枚举
当在类体内定义好各种属性后,外部是可以随便添加属性的,Python中类如何限制实例的属性? Python自带了很多定制类,诸如__slots__,__str__ __slots__ __slots__ ...
- python面向对象高级:定制类
Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类. 比如: __str__ 与__repr____iter____getitem____call__ __str__ 与__r ...
- python定制类详解
1.什么是定制类python中包含很多内置的(Built-in)函数,异常,对象.分别有不同的作用,我们可以重写这些功能. 2.__str__输出对象 class Language(object): ...
随机推荐
- JAXB性能优化
前言: 之前在查阅jaxb相关资料的同时, 也看到了一些关于性能优化的点. 主要集中于对象和xml互转的过程中, 确实有些实实在在需要注意的点. 这边浅谈jaxb性能优化的一个思路. 案列: 先来构造 ...
- MySQL篇,第二章:数据库知识2
MySQL 数据库 2 名词介绍 1.DB(Database) DB就是数据库,存储数据的仓库 2.DBMS(Database Management System) 数据库管理系统 管理数据库的软件, ...
- SEO:网站改版
网站改版分为2种:前端页面改版(不使用301 ),链接结构发生变化(必须使用301) 1.确定一定以及肯定使用301永久重定向,不要使用302跳转 2.非常十分以及极其要求使用百度站长平台的“网站改版 ...
- (22)Ajax的基本使用(实现登录功能和局部刷新以及防止跨站请求伪造攻击)
Ajax的作用 前后端分离的项目,需要交互,就要通过Ajax来完成交互 AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”.即 ...
- Linux 修改yum源
第一种方式: wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo 第二种方式: ...
- 统计cpu相关信息
我的cpu为i3310m 适用类型:笔记本 CPU系列:酷睿i3 3代系列 CPU主频:2.4GHz 三级缓存:3MB 插槽类型:FCBGA1023,FCPGA988 封装大小:37.5×37.5mm ...
- CONTINUOUS MIGRATION
转自:https://pgloader.io/blog/continuous-migration/ After having been involved in many migration proje ...
- UML异步怎么表达
直接看结果 第一虚框和第二虚框是异步的.m1 和m2 没有任何先后关系. 第一虚框和第二虚框是异步的,两者没有任何先后关系.m3和m4是有先后关系的.m3()比m4()先执行.同样m5()和m6().
- 对象的get set方法
- MySQL中正则表达式
正则表达式是用来匹配文本的特殊的串(字符集合),将一个模式(正则表达式)与一个文本串进行比较 从文本文件中提取电话号码 查找名字中间带有数字的文件 文本块中重复出现的单词 替换页面的URL为这些URL ...