内置特殊属性:
类属性:
1.__dict__类的属性
2.__bases__类的所有父类组成的元组
3.__doc__类的文档字符串
4.__name__类的文档字符串
5.__module__类定义所在的模块
print(Person.__dict__)
print(Person.__bases__)
print(Person.__name__)
print(Person.__module__)
print(Person.__doc__)
实例属性:
1.__dict__实例所对应的属性
2.__class__实例对应的类
print(p.__dict__)
print(p.__class__)
私有方法:和私有属性一样,也是在方法前面加两个__,只能在类内部使用,实现机制也是用的命名重整,_类名__方法名
class Person:
def __init__(self):
pass
def __run(self):
print('pao')
def text(self):
self.__run()
p=Person()
p.text()
内置特殊方法:
1.__str__:就是当需要类为str时,就会调用这个方法,其实就有点类似于java里面的string类然后重写tostring方法,这里也是一个道理,比如说我们平常打印一个类都是打印他的内存地址,但是当我们重写了这个方法之后,就会打印出这个方法的返回值,那么什么时候需要类为str呢,最普遍的其实就是打印类了,当然还有强转也是把类强转为str;当我们不重写__str__时,强转出来的str也是地址,但是当我们重写了__str__之后,就会转成这个方法的返回值;如下面代码所示,重写了__str__之后,打印出来的就是这个方法的返回值,然后还有一点就是初始化函数接收了两个参数,然后创建对象的时候就传递了两个参数过去,这个和java里面的构造方法也是如出一辙,完成赋值的过程;
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return '我的名字是%s,年龄是%d'%(self.name,self.age)
p=Person('张三',18)
p1=Person('李四',20)
print(p)
print(p1)
2.__repr__:这个方法其实和__str__这个方法有点类式,用法也是一样,不同的是__str__是针对用户,而__repr__是针对Python解释器,再说明白一点就是用str翻译出来的东西是为了给人看,而用repr翻译出来的东西是给python解释器看:下面的代码就能解释他们之间的区别,分别用str和repr来转换word,但是输出不一样,针对str是给用户看的,字符串就是字符串,不需要引号,但是repr是给python解释器看的,如果单单只是一个字符,会被解释器解释称变量,所以肯定会有引号,这就是区别所在;
word='python'
s1=str(word)
print(s1)
s2=repr(word)
print(s2)
结果:
python
'python'
3.__call__方法:实例对象一般情况下是不能像函数那样被直接调用的,但是当我们重写了__call__方法之后,实例对象就可以直接被调用了,调用实例对象就会执行__call__方法;__call__方法的使用场景:
class CountOff:
def __init__(self,class_):
self.class_=class_
def __call__(self, *args, **kwargs):
print('我是%s的同学%s'%(self.class_,*args))
one=CountOff('一班')
one('张三')
one('李四')
two=CountOff('二班')
two('王麻子')
two('展昭')
索引操作:就是让对象可以像字典那样通过key,value来操作:主要就是通过重写__setitem__,__getitem__以及__delitem__三个方法
class index:
def __init__(self):
self.text={}
def __setitem__(self, key, value):
self.text[key]=value
def __getitem__(self, item):
return self.text[item]
def __delitem__(self, key):
del self.text[key]
inde=index()
inde['ceshi']='zhi'
print(inde['ceshi'])
del inde['ceshi']
print(inde.text)
切片操作:就是使得对象可以像字符串或者列表一样完成切片操作:和索引操作一样,切片操作还是重写__setitem__,__getitem__以及__delitem__三个方法,
对象的比较操作:在python2.x版本里面两个对象的比较操作比较的是对象的内存地址,在python3.x版本两个对象是不能进行比较的,除非自己去定义对象的比较规则,也就是重写比较方法,这样对象之间就能进行比较了:
比较操作的注意事项:我们都知道大于的反向就是小于,那么我们有没有必要重写6个这么多方法呢,其实没必要,解释器会帮我们做一些事,比如说当我们只重写了__lt__方法,我们用小于操作符比较的时候会调用它,当我们使用大于操作符的时候也会调用它,不过会调换位置,比如说a<b,调用的时候就是直接是a<b,当我们操作符是a>b的时候,调用__lt__方法就会变成b<a,就是调换顺序,但是需要注意的是没有叠加操作,比如a<=b,不会同时去调用__lt__和__eq__;
比较操作扩展:其实按照逻辑来说,我们只要有小于和等于,其他的比较运算都可以推导出来,那么有没有其他的库可以帮我们实现呢?答案是有的,就是用functools的装饰器,装饰器本身存在的意义就是让类或者函数增加功能,所以我们在给类加上这个装饰器之后,会使得这个类多了这么多功能:
上下文布尔值:就是针对于类布尔值的判定,我们知道针对布尔值是非零即真,非空即真,那我们的实例对象,其实无论如何都会为真,其实这个也是可以控制的,就是重写__bool__这个方法,比如:判定一个人是否成年:
class Person:
def __init__(self,age,name):
self.age=age
self.name=name
def __bool__(self):
return self.age>=18
def adult(value):
if value:
print('%s已经成年'%value.name)
p1=Person(10,'张三')
p2=Person(20,'李四')
adult(p1)
adult(p2)