テスト開発のためのPythonコアノート(20):高度なメソッド組み込みクラス

クラスを定義すると、Pythonは自動的にいくつかのメソッドを提供しますが、そのほとんどはオブジェクトクラスまたは型クラスから継承されます。これらのメソッドをオーバーライドして、特定の操作を実装できます。

20.1印刷時にオブジェクトを読みやすくする

print()を使用してオブジェクトを印刷する__str__()と、関数のコンテンツが表示されます。インスタンスを直接実行すると、印刷されたオブジェクトに__repr__()関数のコンテンツが表示されます。したがって、実装__str__()__repr__()これら2つの方法により、オブジェクトの印刷は人間の読み取りとより一致するようになります。例えば

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クラスオブジェクトに反復をサポートさせる

すべてのコンテナタイプが反復ループの...in...をサポートしていることがわかっています。forステートメントは実際には2つのことを行います。最初にイテレータを取得します。つまり、__iter__()関数が呼び出されます。2つ目は、ループのプロセスであり、ループ__next__()内で関数を呼び出します。実際、カスタムクラスは、これら2つのメソッドが実装されている限り、クラスのオブジェクトをforループで繰り返すこともできます。

たとえば、クラスで実装されたフィボナッチ数列:

class Fib:
    def __init__(self):
        self.a, self.b = 0, 1  # 初始化两个计数器a,bdef __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オブジェクトを呼び出し可能にする

私たちが通常定義する関数、組み込み関数、クラスはすべて呼び出し可能なオブジェクトです。直感的には、それらの後に1対の括弧を追加できますが、1対の括弧()をオブジェクトに適用できる場合は、このオブジェクトです。これは呼び出し可能オブジェクトと呼ぶことができ、関数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__このメソッドは、主にクラス(int、str、tupleなど)を継承する場合に使用され、プログラマーにこれらのクラスのインスタンス化プロセスをカスタマイズする機会を提供します。カスタムメタクラスメタクラスの実現もあります。

__new__典型的なアプリケーションは、シングルトンパターンを作成することです。

シングルトンモードの原理は、クラス属性にシングルトン決定ビットフラグを追加し、このフラグを使用してクラスがインスタンス化されているかどうかを判断することです。クラスがインスタンス化されている場合は、インスタンス化されたオブジェクトが返されます。

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))

シングルトンから継承するクラス__new__は、オーバーライドされない限りシングルトンになります。

20.52つのオブジェクト比較ロジックのカスタマイズ

このメソッドは、2つのオブジェクトが等しいかどうかが判別されたときにトリガーされます__eq__このメソッドでは、2つのオブジェクトが等しいためのルールを定義できます。2つのオブジェクトのサイズを比較するためのルールを定義するメソッド__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

おすすめ

転載: blog.csdn.net/liuchunming033/article/details/107934981