测试开发之Python核心笔记(20): 内置高级方法(转载)

当我们定义了一个类之后,Python会自动为我们提供一些方法,这些方法大部分是从object类或者type类继承来的。我们可以覆盖这些方法实现特定的操作。

20.1 让对象打印出来更易读
用print()打印对象,会展示__str__()函数的内容,直接运行实例的时候,打印的对象,会展示__repr__()函数的内容。因此可以通过实现__str__()和__repr__()这两方法,让对象打印出来更符合人类阅读。比如

class Student:
def init(self, name, age):
self.name = name
self.age = age

def str(self): # print()时调用
return ‘Student object (name=%s, age=%d)’ % (self.name, self.age)

repr = str


print(Student(“Jim”, 20)) # 打印__str__函数的内容,Student object (name=Jim, age=20)

20.2 让类对象支持迭代
我们知道容器类型都支持for … in… 进行迭代循环。for语句其实做了两件事。第一件事是获得一个迭代器,即调用了__iter__()函数。第二件事是循环的过程,循环调用__next__()函数。其实,自定义的类,只要实现了这两个方法,那么类的对象也是可以被for循环迭代的。

比如斐波那契数列,用类实现:

class Fib:
def init(self):
self.a, self.b = 0, 1 # 初始化两个计数器a,b

def iter(self):
return self # 返回一个迭代对象,实例本身就是迭代对象,故返回自己

def next(self): # for循环时就是调用这个方法获取下一个值
self.a, self.b = self.b, self.a + self.b # 计算下一个值
if self.a > 10000: # 退出循环的条件
raise StopIteration()
return self.a # 返回下一个值


for i in Fib():
if i > 20:
break
print(i)

20.3 让对象可以被调用
我们平时自定义的函数、内置函数和类都属于可调用对象,直观的感受就是可以在他们后面加上一对小括号,但凡是可以把一对括号()应用到某个对象身上,这个对象就可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable()。

callable(0) # 函数返回 False
def add(a, b):
return a + b
callable(add) # 函数返回 True

如果在类中实现了 call 方法,那么实例对象也将成为一个可调用对象。即可以实例后跟小括号了,调用后的结果就是__call__方法的内容。看个例子:

class Student:
def init(self, name):
self.name = name

def call(self):
print(‘My name is %s.’ % self.name)


s = Student(‘Michael’)
s() # 实例变成了Callable的了,输出My name is Michael

这有什么实际用处呢?下面看一个例子,利用__getattr__和__call__,实现动态调用,动态生成url字符串。

class Chain:

def init(self, path=’’):
self._path = path

def getattr(self, path):
“”“调用不存在的属性时,会执行这个方法,方法效果是将path用/拼接起来,返回一个实例”""
return Chain(’%s/%s’ % (self._path, path))

def call(self, path):
“”“当实例被调用时,会执行这个方法,方法效果是实例里面的参数也用/拼接起来,返回一个实例”""
return Chain(’%s/%s’ % (self._path, path))

def str(self):
return self._path

repr = str


if name == ‘main’:
print(Chain().status.user.timeline.list) # 每一个"."就是一次调用__getattr__方法
print(Chain().users(‘michael’).repos) # Chain().users根据__getattr__的作用会返回一个实例,加上()后回到用__call__方法

20.4 手动创建一个实例对象
__new__方法负责创建一个实例对象,在对象被创建的时候Python解释器自动调用该方法,它是一个类方法。__new__方法在返回一个实例之后,Python解释器会继续自动的调用__init__方法,对实例进行初始化。如果__new__方法不返回值,或者返回的不是实例,那么Python解释器就不会自动的去调用__init__方法。__new__方法主要是当继承一个class时(比如int, str, tuple), 给程序员提供一个自定义这些类的实例化过程的机会。还有就是实现自定义的元类metaclass。

__new__的一个典型应用是创建单例模式。

单例模式的原理,就是通过在类属性中添加一个单例判定位flag,通过这个flag判断类是否已经被实例化过了,如果类已经被实例化过了就返回实例化的对象。

class Singleton:
# 重写父类的__new__方法,__new__是个类方法,第一个参数是cls,必须有返回值
def new(cls, *args, **kwargs): # 自定义类实例化对象的过程
# __new__生成的对象放入cls的_instance属性中, 如果cls不存在_instance
if not hasattr(cls, “_instance”):
cls._instance = super().new(cls, *args, **kwargs) # 调用父类__new__创建实例
# 如果cls存在_instance,直接返回,不要生成新的对象
return cls._instance


class MyClass(Singleton):
pass


s1 = MyClass()
s2 = MyClass()
s3 = MyClass(“s3”)
s4 = MyClass(“s4”)
print(id(s1), id(s2), id(s3), id(s4))

继承至Singleton的类,在不重写__new__的情况下都将是单例模式。

20.5 自定义两个对象比较逻辑
当判断两个对象是否相等时,触发__eq__方法。可以在这个方法中定义两个对象相等的规则。另外还有__lt__和__gt__方法,用来定义两个对象大小比较的规则。例如:

class Student:
def init(self, name, age):
self.name = name
self.age = age

def eq(self, other): # 定义内置方法,自定义两个对象相等的逻辑
return self.dict == other.dict # 两对象空间的属性值都相等,两个对象被认为相等。

def lt(self, other):
return self.age < other.age


if name == ‘main’:
s1 = Student(“李四”, 20)
s2 = Student(“李四”, 20)
print(s2 == s1) # True
print(s2 is s1) # False
s3 = Student(“王五”, 19)
print(s1 > s3) # True

原文链接:https://blog.csdn.net/liuchunming033/article/details/107934981?utm_medium=distribute.pc_feed.none-task-blog-personrec_tag-18.nonecase&depth_1-utm_source=distribute.pc_feed.none-task-blog-personrec_tag-18.nonecase&request_id=5f4393a7cea070620e93eb0d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值