이 글은 Python의 새로운 클래스 메소드, init 인스턴스 메소드 및 싱글톤 모드(예제 포함)를 소개합니다. 필요한 친구들이 참고할 수 있기를 바랍니다.
"모든 클래스가 Python 싱글턴 모드인가요?" 어느 날 동료가 이런 질문을 했습니다. 이것은 이상한 질문입니다. 아마도 당신도 그렇게 생각할 것입니다. 여기에서는 설명을 생략하고 먼저 __new__ 및 __init__ 메서드를 살펴보겠습니다.
new 및 init
__new__ 메소드는 새 스타일 클래스에 속합니다. 즉, 객체 클래스에 속합니다. 이는 정적 메서드이지만 첫 번째 매개 변수는 클래스(cls)여야 하며 이는 클래스 메서드와 약간 비슷합니다. 이 특수 메서드가 호출되면 클래스(cls)의 새 인스턴스가 생성되고 반환됩니다. 인스턴스가 생성된 후 인터프리터는 인스턴스와 기타 매개변수를 인스턴스의 초기화 함수 __init__에 전달하여 인스턴스를 초기화합니다.
그래서 __new__ 메서드는 인스턴스를 생성하는 데 사용되는 클래스 메서드이고, __init__ 메서드는 인스턴스를 초기화하는 데 사용되는 인스턴스 메서드입니다.
__new__ 메서드는 클래스를 인스턴스화할 때 호출됩니다. 이 메서드를 재정의하는 방법은 다음과 같습니다.
class A(object): def __new__(cls, *args, **kwargs) return super(A, cls).__new__(cls, *args, **kwargs)
__new__ 메서드가 cls 인스턴스를 반환하지 않으면 new 인스턴스의 __init__ 메서드는 호출되지 않습니다. Python 3.3 이후에는 새 메서드가 더 이상 추가 매개변수를 받지 않습니다. 그렇지 않으면 TypeError: object()가 매개변수를 사용하지 않는다는 예외가 발생합니다.
__init__ 메서드는 인스턴스가 생성된 후에 호출됩니다. 이 메서드는 __new__ 메서드로 생성된 인스턴스에 대해 일부 초기화 작업만 수행합니다. 새 메소드가 인스턴스를 반환하는 경우 init 메소드는 항상 호출된다는 점에 유의하세요(싱글톤을 구현하기 위해 새 메소드를 사용할 때 특히 주의해야 합니다)
몇 가지 확인을 수행할 수 있습니다. # 🎜🎜#
class Foo(object): def __new__(cls, m, n): print "__new__ is called" return super(Foo, cls).__new__(cls, m, n) def __init__(self, m, n): print "__init__ is called" self.m = m self.n = n def __repr__(self): return "Foo(m={self.m}, n={self.n})".format(self=self) def __str__(self): return self.__repr__() if __name__ == "__main__": f = Foo(1, 2) print f
__new__ is called __init__ is called Foo(m=1, n=2)
#입니다. 🎜🎜#__init__ 메소드는 일반적으로 클래스를 정의할 때 포함되며, 흔히 사용되는 메소드이기도 합니다. __new__ 메소드는 거의 사용되지 않습니다. 그렇다면 그 용도는 무엇입니까?
new 메소드 함수
1. int, str , tuple로), 사용자 정의 인스턴스화 프로세스를 제공합니다. __init__ 메서드에서 모든 쓰기 작업을 수행하면 유효하지 않을 수 있기 때문입니다. 예:
class CustomInt(int): def __init__(self, v): super(CustomInt, self).__init__(self, abs(v)) print CustomInt(-1) # 输出:-1
이는 원하는 효과를 얻지 못할 수도 있습니다. 하지만 이는 __new__
메소드를 재정의하여 달성할 수 있습니다:
class CustomInt(int): def __new__(cls, v): return super(CustomInt, cls).__new__(cls, abs(v)) print CustomInt(-1) # 输出:1
2. ). 메타클래스는 클래스를 생성하는 방법을 정의하는 데 사용됩니다. 해당 개념은 약간 복잡할 수 있으므로 여기서는 자세히 설명하지 않습니다. __new__
方法来实现:
class Singleton(object): def __new__(cls): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance assert Singleton() is Singleton() # 断言成功
2、 实现自定义的元类(metaclass)。元类就是用来定义如何创建类,它的概念可能稍微复杂些,这里不做详细讨论。
3、 实现单例。由于类产生实例的过程是通过 __new__
方法来控制的,因此重写该方法来单例模式是非常方便的:
print Singleton(), Singleton()
所谓单例模式就是每次初始化都返回同一个实例,所以两次初始化得到的对象的内存地址应该是一样的:
<__main__.Singleton object at 0x10d698650> <__main__.Singleton object at 0x10d698650>
结果应该是显而易见的:
from functools import wraps def singleton(cls): instances = {} @wraps(cls) def getinstance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return getinstance @singleton class MyClass(object): def __init__(self): pass
说到单例模式,除了用 __new__
方法实现外,还有一些其他的方式,如装饰器、元类等。不同方式的实现有不同的作用,元类属于 Python 中更为高级的特性,本文不做讨论,我们来看一下用装饰器实现单例的方法。
装饰器(decorator)可以动态地修改一个类或函数的功能,即类也可以被装饰器装饰。因此可以使用装饰器来装饰某个类,使其被初始化时只生成一个实例:
>>> class A(object): ... pass ... >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450> >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450> >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450>
需要注意的是,使用装饰器实现单例时,类已经变成了一个函数,而不再是类。 如上用上例中 MyClass 初始化实例时,实际上调用的是被装饰后返回的 getinstance 函数。
用 __new__
实现单例和用装饰实现单例的区别是,前者前者都是会调用 __init__
__new__
메서드를 통해 제어되므로 싱글톤 모드를 사용하도록 이 메서드를 다시 작성하는 것이 매우 편리합니다. #🎜🎜#>>> A() is A() False
>>> class A(): ... pass ... >>> print(A(), A()) <__console__.A object at 0x10fe7afd0> <__console__.A object at 0x10fed79e8> >>> print(A(), A()) <__console__.A object at 0x10fec0cc0> <__console__.A object at 0x10feda160> >>> print(A(), A()) <__console__.A object at 0x10fe7afd0> <__console__.A object at 0x10fed7940> >>> A() is A() False
__new__
메서드를 사용하는 것 외에도 몇 가지 다른 방법이 있습니다. 데코레이터, 요소 클래스 등과 같은 구현 방법에 따라 효과도 달라집니다. 메타클래스는 Python의 고급 기능이므로 이 문서에서는 데코레이터를 사용하여 싱글톤을 구현하는 방법을 살펴보겠습니다. #🎜🎜##🎜🎜#데코레이터는 클래스나 함수의 기능을 동적으로 수정할 수 있습니다. 즉, 클래스도 데코레이터에 의해 데코레이트될 수 있습니다. 따라서 데코레이터를 사용하여 클래스가 초기화될 때 하나의 인스턴스만 생성되도록 클래스를 장식할 수 있습니다. #🎜🎜#rrreee#🎜🎜#데코레이터를 사용하여 싱글톤을 구현할 때 클래스는 다음과 같이 됩니다. 클래스 대신 함수. 위의 예에서 MyClass를 사용하여 인스턴스를 초기화할 때 실제로 호출되는 것은 데코레이션된 후 반환되는 getinstance 함수입니다. #🎜🎜##🎜🎜#__new__
를 사용하여 싱글톤을 구현하는 것과 데코레이션을 사용하여 싱글톤을 구현하는 것의 차이점은 전자가 __init__
메서드를 호출한다는 것입니다. 각 초기화 중에 서로 다른 매개변수가 사용됩니다. 반환된 인스턴스는 동일하지만 인스턴스의 속성은 재설정되며, 후자는 나중에 다르게 전달되더라도 항상 첫 번째 초기화 중에 설정된 예제를 반환합니다. 매개변수. #🎜🎜#接着,我们再来看一个 “奇怪” 的现象:
>>> class A(object): ... pass ... >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450> >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450> >>> print A(), A() <__main__.A object at 0x104765450> <__main__.A object at 0x104765450>
是不是感觉有些难以置信,print 语句后两次创建的对象应该是不一样的,而他们却莫名奇妙的一样。这就是我讨论本文内容的原因。
一次同事问我,Python 中的类都是单例模式?我当时一脸懵逼,听了他的描述,我自己也试了下,果然存在如上所示的“奇怪”现象。于是我就去了解了 Python 单例模式的实现,在了解到 __new__
的实现方式时,就想对 __new__
和 __init__
有一个更加深入的了解。于是就有了本文所讨论的内容。
然后,我想着用 is 来判断下他们是否真的是同一个实例:
>>> A() is A() False
我没有对 CPython 的源码进行过全面的阅读,所以对其很多内部的实现机制不是太了解。我猜 Python 解释器在内部可能做了优化,像 print A(), A()
这样的语句,解释器认为没有必要创建不同的对象,直接返回同一个实例的引用得了。是不是觉得解释器有些自作聪明!而当 A() is A()
这样的表达式出现时,解释器想,我不能再自作聪明,那样可能会误导别人。可是,在 print 语句那样的用法时,就已经误导我了,我都差点开始怀疑人生了!
从语法来看,大家应该知道,我在测试时使用的 Python 2。我后来也试了下 Python 3:
>>> class A(): ... pass ... >>> print(A(), A()) <__console__.A object at 0x10fe7afd0> <__console__.A object at 0x10fed79e8> >>> print(A(), A()) <__console__.A object at 0x10fec0cc0> <__console__.A object at 0x10feda160> >>> print(A(), A()) <__console__.A object at 0x10fe7afd0> <__console__.A object at 0x10fed7940> >>> A() is A() False
我想,这样的结果才是不会让人困惑的。可能是 Python 社区意识到了这个问题并在 Python3 中进行了修正。这样的修正是好的,否则对于像我同事那样初次使用 Python 的人来说是很困惑的。
个人认为,Python3 对过去的一些“错误”的修正是好的。例如将 print 改为函数,提供了丰富的参数来控制输出的样式;对编码的调整等等。
위 내용은 Python의 새로운 클래스 메서드, init 인스턴스 메서드 및 싱글톤 모드 소개(예제 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!