任何事,任何人,都会成为过去,不要跟它过不去!
总结:
- 直接作为str()函数、format()函数、print()函数参数调用时,调用_str_方法; 被间隔作为参数被调用时,调用_repr_方法;
- print 打印不作数;数据类型需要判断,打印的不做数;注意不能通过判断是否带引号判断输出值的类型,类型判断要使用type或isinstance
面向对象中,任何一个实例对象都可以hash,因为object实现了,用它的内存地址参与进来做这事;
这个对象我们需要特殊的去构造这个hash值;我们能不能hash函数设定一个你想指定的hash值呢?set、dict中用到hash;
魔术方法(Magic Methods),顾名思义,就是可以为代码中的类赋予某种“魔力”的方法(methods)。有了它,你可以构造出非常巧妙、优雅的代码。
1. _bool_
class A:pass
print(A) # 类有字符串的表达形式;
print(bool(A))
# 等价形式
if A:
print(1,'True')
if A():
print(2,'True')
print(bool(A),bool(A()))
print(dir(A)) # A,A() 内没有__bool__,默认它是真;
#---------------------------------------------------------------------
<class '__main__.A'>
True
1 True
2 True
True True
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
_bool_ 和 _len_
方法 | 意义 |
---|---|
_bool_ | 内建函数bool(),或者对象放在逻辑表达式的位置,调用这个函数返回布尔值。没有定义 bool (),就找 len ()返回长度,非0为真。如果 len ()也没有定义,那么所有实例都返回真 |
_len_: | 尝试调用len()时触发,可用来检测对象参数的信息。self表示当前对象,返回值必须时整型。 |
class B:
def __bool__(self): # B真; B()实例 return False;
return False
if B:
print('True')
if B():
print('True')
else:
print('False')
print('-'*40)
class C:
def __len__(self):
return False
if C:
print(True)
if C():
print(True)
else:
print(False)
print(C.__dict__)
#--------------------------------------------------------------------------------------------------------------------------
True
False
----------------------------------------
True
False
{'__module__': '__main__', '__len__': <function C.__len__ at 0x000001E41D1559D8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
# 同时存在bool和len;
print('-'*40)
class C:
def __bool__(self):
return False
def __len__(self):
return 5
if C:
print(True)
if C():
print(True)
else:
print(False)
print(C.__dict__)
#------------------------------------------------------------------------------------
True
False
{'__module__': '__main__', '__bool__': <function C.__bool__ at 0x000001E41D14AE18>, '__len__': <function C.__len__ at 0x000001E41D14A400>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}
真值测试的运行机制
了解了两种魔术方法后,我们对真值测试的流程做一个介绍。假设我们要对一个Python对象进行真值测试:
- 如果该对象定义了bool方法,则依bool方法返回的真值作为该对象的真值。
- 否则,如果该对象定义了len方法,则根据len方法返回的整数进行判断,返回值为0则真值为False,不为0则真值为True;
- 否则,该对象的真值为True;
内置函数bool()
Python有一个内置函数bool(),它接受一个对象作为参数,返回的就是该对象在Python下进行真值测试的结果,即该函数返回一个bool变量,该变量的值的判断方法与上面介绍的真值测试完全一致。
2. 可视化
方法 | 意义 |
---|---|
_repr_ | 内建函数repr()对一个对象获取字符串表达。调用 _repr_ 方法返回字符串表达,如果 repr 也没有定义,就直接返回object的定义;就是显示内存地址信息 |
_str_ | str()函数、format()函数、print()函数调用,需要返回对象的字符串表达。如果没有定义,就去调用 repr 方法返回字符串表达,如果 repr 没有定义,就直接返回对象的内存地址信息 |
_bytes_ | bytes()函数调用,返回一个对象的bytes表达,即返回bytes对象 |
class A:
def __init__(self,name):
self.name = name
def __repr__(self):
return 'repr name={}'.format(self.name)
def __str__(self):
return 'str name={}'.format(self.name)
print(A)
# 三种方法找 __str__:
print(A('tom')) # str: 找str
print(str(A('ben'))) # 同上;
print('{}'.format(A('jerry')))
print('-'*30)
print(repr(A('tom'))) # 找repr;
print(repr('{}'.format(A('jerry')))) # str(str); 先求format(str),,
#-----------------------------------------------------------------------------------------------------------------------------
<class '__main__.A'>
str name=tom
str name=ben
str name=jerry
------------------------------
repr name=tom
'str name=jerry'
import json
class A:
def __init__(self,name):
self.name = name
def __repr__(self):
return 'repr name={}'.format(self.name)
def __str__(self):
return 'str name={}'.format(self.name)
def __bytes__(self):
#return 'abc'.encode()
#return self.name.encode()
return json.dumps(self.__dict__).encode()
a = A('tom')
print([a, a]) # print 与实例对象a 隔了一层打印 repr;
print(str({a,a})) # str 与 a 隔了一层;
print('{}'.format(*{a,a})) # 解构不是 {},中间没有隔层;
print(bytes(a))
#------------------------------------------------------------------------------------------
[repr name=tom, repr name=tom]
{repr name=tom}
str name=tom
b'{"name": "tom"}'
总结:
- 同时存在_str_ _repr_ ;直接作为str()函数、format()函数、print()函数参数调用时,调用_str_; 被间隔作为参数被调用时,调用_repr_参数;
- 只存在 _repr_ ;打印repr方法;只存在str,打印内存地址;都不存在,打印地址;
- print 打印不作数;数据类型需要判断,打印的不做数;注意不能通过判断是否带引号判断输出值的类型,类型判断要使用type或isinstance
网友评论