Python에서 __new__ 메소드의 역할을 자세히 설명하는 기사
머리말
파이썬에서 클래스 생성자의 __new__ 메서드의 기능은 무엇인가요?
Python 클래스의 일부 메서드 이름과 속성 이름은 앞뒤에 __ 이중 밑줄이 옵니다. 이러한 메서드와 속성은 일반적으로 Python의 특수 메서드 및 속성입니다. 이러한 메서드를 재정의하거나 직접 호출하여 특수 기능을 구현합니다. 오늘은 실제 프로그램에서 __new__ 구축 방법의 적용 시나리오에 대해 이야기해 보겠습니다.
우리는 일반적인 초기화 __init__ 메소드를 알고 있으며 이를 다시 작성하여 원하는 초기화 로직을 구현할 수 있습니다. 최근에는 데이터 리소스 로딩 및 캐싱 메커니즘 구현과 같은 실제 비즈니스 개발 과정에서 일종의 문제가 발생했습니다. 그 중 생성자는 __init__() 및 __new__입니다. 합리적으로 사용하면 프로그램 성능이 효과적으로 향상됩니다.
모두가 깊이 이해하고 각자의 비즈니스 요구에 따라 유연하게 사용하여 코드를 더욱 우아하게 만들 수 있기를 바랍니다.
1. __new__ 메소드 소개
다음으로, 클래스 초기화 과정에서 __new__ 메소드의 존재에 대해 예제를 통해 점차 자세히 설명하겠습니다!
1. 데이터 로딩 초기화 + 클래스 인스턴스 파싱
class Solution(object): def __init__(self, name=None,data=None): self.name = name self.data = data #初始化加载数据 self.xml_load(self.data) def xml_load(self,data): print("初始化init",data) def Parser(self): print("解析完成finish",self.name) a = Solution(name="A111",data=10) a.Parser() b = Solution(name="A112",data=20) b.Parser() # print(a)与 print(b)返回了类的名称和对象的地址 print(a) print(b) # 可以使用内置函数id()查看python对象的内存地址 print(id(a)) print(id(b)) 初始化init 10 解析完成finish A111 初始化init 20 解析完成finish A112 <__main__.Solution object at 0x0000024A3AF28D48> <__main__.Solution object at 0x0000024A3B055C48> 2517839809864 2517841042504
참고:
1) 코드 인스턴스화 클래스 프로세스
일반적으로 코드에서 클래스 인스턴스를 초기화하려면 __init__() 메서드를 사용하세요. , 실행된 첫 번째 호출은 __new__() 메서드가 정의된 클래스에서 재정의되지 않은 경우 Python은 기본적으로 부모 클래스의 __new__() 메서드를 호출하여 인스턴스를 생성합니다. 공간을 생성한 다음 매번 인스턴스화된 객체를 생성한 다음 열린 공간을 사용하여 인스턴스화된 객체를 저장합니다. 인스턴스화된 객체를 다시 생성할 때 새로운 방법을 사용하여 인스턴스화된 객체를 저장할 공간을 엽니다. 객체를 상속받은 클래스에만 이 메서드가 있다는 점에 유의하세요.
2), 메모리 주소와 객체는 서로 변환될 수 있습니다
#通过_ctypes的api进行对内存地址的对象 import _ctypes obj = _ctypes.PyObj_FromPtr(id(a)) #打印出来通过内存地址寻找到的对象 print(obj)
print(id(a)) 및 print(id(b)) 메모리 주소(십진수)를 인쇄하고, print(a) 및 print( b ) 클래스 이름과 객체의 주소가 반환되지만 둘은 동일하지 않습니다. 클래스가 인스턴스화될 때마다 다른 개체 주소가 생성되고 할당되므로 코드 인스턴스화 프로세스 중에 반환되는 클래스 개체의 주소 참조도 다릅니다.
2. 데이터 로딩 초기화 및 새 메소드 재작성 + 클래스 인스턴스 구문 분석
class Solution: """ 注:new方法是为实例化对象创建空间的方法,现在new方法被改写,没有将实例化对象引用返回给python的解释器 无法为实例化对象创建空间存储,所以运行代码会报错。也没有完成初始化操作。 """ def __new__(cls, *args, **kwargs): print("对象创建空间") cls.instance = super().__new__(cls) print(cls.instance) # return cls.instance #若未返回实例对象引用,实例化方法将报错:AttributeError: 'NoneType' object has no attribute 'Parser' def __init__(self,name,data): self.name = name self.data = data self.xml_load(self.data) def xml_load(self,data): print("初始化init", data) def Parser(self): print("解析完成finish",self.data) a = Solution("A111",10) a.Parser() print(id(a))
참고:
1) __init__() 메소드와 __new__() 메소드
__new__() 메소드의 차이점은 인스턴스와 클래스를 생성하는 데 사용됩니다. 인스턴스화 이전에 먼저 호출되는 클래스 메서드이자 정적 메서드입니다. __init__() 메서드는 인스턴스를 초기화하는 데 사용됩니다. 이 메서드는 인스턴스 개체가 생성된 후 호출되며 클래스 인스턴스 개체의 일부 초기 값을 설정하는 데 사용됩니다.
클래스에 __init__() 메서드와 __new__() 메서드가 동시에 나타나면 __new__() 메서드가 먼저 호출된 다음 __init__() 메서드가 호출됩니다. __new__() 메서드는 인스턴스 생성의 첫 번째 단계입니다. 실행 후 생성된 클래스의 인스턴스를 반환해야 합니다. 그렇지 않으면 오류가 보고되고 __init__() 메서드를 실행할 수 없습니다. 그 중 __init__() 메서드는 어떤 정보도 반환하지 않습니다.
2), __new__() 메소드
def __new__(cls, *args, **kwargs): print(cls)# cls 代表的是Solution这个类本身<class'__ main __.Solution'> cls.instance = super().__new__(cls)# object().__ new __() print(cls.instance) return cls.instance
super() 및 object.__new__(cls)를 다시 작성하면 상위 클래스의 새 메소드를 호출하여 열 수 있습니다. 따라서 return을 추가해야 합니다. 코드의 실행 순서는 다음과 같습니다. 먼저 새 메서드를 실행한 다음 init 메서드를 실행하고 마지막으로 다른 메서드를 실행합니다.
2. 싱글턴 패턴
싱글턴 패턴의 원래 정의는 "디자인 패턴"에 나와 있습니다. "클래스에 인스턴스가 하나만 있는지 확인하고 이에 액세스할 수 있는 전역 액세스 지점을 제공합니다."
싱글턴의 주요 용도는 시스템 로그 출력, 운영 체제의 작업 관리자 등과 같이 세계의 단 하나의 인스턴스에만 액세스할 수 있도록 해야 하는 상황.
1. 새로운 방법을 사용하여 싱글톤 모드를 구현하는 방법은 무엇입니까?
class Solution: # 1、记录第一个被创建对象的引用,代表着类的私有属性 _instance = None # 静态变量 存储在类的命名空间里的 def __init__(self,name,data): self.name = name self.data = data self.xml_load(self.data) def __new__(cls, *args, **kwargs): # 2.判断该类的属性是否为空;对第一个对象没有被创建,我们应该调用父类的方法,为第一个对象分配空间 if cls._instance == None: # 3.把类属性中保存的对象引用返回给python的解释器 cls._instance = object.__new__(cls)# 3 return cls._instance # 如果cls._instance不为None,直接返回已经实例化了的实例对象 else: return cls._instance# 必须把地址返回给new方法,让它有存储空间 def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name) a = Solution("A11",10)#第一次开辟一个对象空间地址,后面创建都是在该地址上进行的 a.Parser() b = Solution("A12",20)#b把a覆盖掉 b.Parser() print(id(a)) print(id(b)) # 内存地址,而且它们的内存地址都是一样的 print(a.name) print(b.name)
初始化init A11 10 解析完成finish A11 初始化init A12 10 解析完成finish A12 2465140199816 2465140199816 A12 A12
참고:
1) 싱글톤 모드에는 항상 공간이 하나만 있으며 이 공간은 항상 재사용됩니다.
먼저 생성된 객체의 참조를 기록하기 위해 클래스의 private 속성인 _instance를 정의합니다. cls._instance가 None이면 클래스가 아직 인스턴스화되지 않았음을 의미하며, 클래스를 인스턴스화하고 인스턴스 객체를 반환합니다.
다음 데이터 테스트를 통해 print(obj.name, obj.data)의 마지막 출력이 A12임을 알 수 있습니다. "A11"이 처음 인쇄되면 속성이 비어 있습니다. 이 속성을 저장할 공간을 엽니다. 두 번째 적중 이후 공간이 열렸습니다. else 문을 실행하고 "A12"를 원래 공간으로 직접 반환하여 이전 표지 데이터를 덮어씁니다.
def task(id,data): obj = Solution("{0}".format(id), "{0}".format(data)) print(obj.name, obj.data) import threading ID=["A11","A12","A13","A14","A12"] DATA=[10,20,30,40,20] for i in range(5): t = threading.Thread(target=task(ID[i],DATA[i]), args=[i, ]) t.start()
<__main__.Solution object at 0x00000221B2129148> 初始化init A11 10 A11 10 初始化init A12 20 A12 20 初始化init A13 30 A13 30 初始化init A14 40 A14 40 初始化init A12 20 A12 20
2), 싱글턴 모드의 또 다른 구현 방법
def __new__(cls,*args,**kwargs): # hasattr查询目标并判断有没有,not1==1返回的是False # if语句后面的 # not 条件整体为True时,执行cls.instance = object....代码 # if语句后面的 # not 条件整体为False时,执行return代码 if not hasattr(cls,"instance"): # hasattr查、判断的作用 cls.instance = object.__new__(cls) return cls.instance
2. 초기화 방법을 한 번만 실행하도록 클래스를 제어하는 방법은 무엇인가요?
위에서는 싱글톤 모드 개체 공간의 재사용을 실현하지만 때로는 시스템 리소스를 낭비하는 빈번한 요청(예: 데이터베이스 연결 요청 데이터)을 피하기 위해 초기화 프로세스를 한 번만 로드하고 싶을 때도 있습니다.
class Solution: #定义类变量 # 记录第一个被创建对象的引用,代表着类的私有属性 _instance = None #记录是否执行过初始化动作 init_flag = False def __init__(self,name,data): self.name = name self.data = data #使用类名调用类变量,不能直接访问。 if Solution.init_flag: return self.xml_load(self.data) # 修改类属性的标记 Solution.init_flag = True def __new__(cls, *args, **kwargs): # 判断该类的属性是否为空;对第一个对象没有被创建,我们应该调用父类的方法,为第一个对象分配空间 if cls._instance == None: # 把类属性中保存的对象引用返回给python的解释器 cls._instance = object.__new__(cls) return cls._instance #如果cls._instance不为None,直接返回已经实例化了的实例对象 else: return cls._instance def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name) a = Solution("A11",10)#第一次实例化对象地址,后面创建都是在该地址上进行的 a.Parser() b = Solution("A12",20)#b把a覆盖掉 b.Parser() print(id(a)) print(id(b)) print(a.name) print(b.name)
참고:
1) 싱글톤 모드에서는 초기화 프로세스를 한 번만 로드하세요.
这时候我们在类空间中再添加一个init_flag属性来记录是否已经执行过初始化操作即可实现加载一次初始化过程。从以上两次实例化过程结果来看,对象引用地址不变,结果被最后一次实例化数据覆盖且初始化init只被打印一次。
2)、单例模式下一次资源加载注意点
单例模式下控制类仅进行一次初始化过程适用于资源一次性加载进缓存的过程,对于多进程应用可采用多例模式实现。
三、多例模式
多个实例对象空间引用地址完全独立,从而保持避免不同请求资源不被占用。将同一个对象请求归为同一个实例。
class Solution: ##定义类实例化对象字典,即不同的实例对象对应不同的对象空间地址引用 _loaded = {} def __init__(self,name,data): self.name = name self.data = data self.xml_load(self.data) def __new__(cls, name,*args): if cls._loaded.get(name) is not None: client = cls._loaded.get(name) print(f"已经存在访问对象 {name}") print(client) return client # 把类属性中保存的对象引用返回给python的解释器 print(f"正在创建访问对象 {name}") client = super().__new__(cls) # 为该类实例name添加一个空间对象地址引用 print(client) cls._loaded[name] = client return client def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name) if __name__ == '__main__': print("多例模式实例") a = Solution("A11",10) a.Parser() b = Solution("A11",10) b.Parser() c = Solution("A12", 20) c.Parser() print(f"{a is b}") print(a.name) print(b.name) print(c.name)
注:
1)、多例模式始终具有多个空间,不同空间完全独立。
我们在类空间中定义类实例化对象字典,即建立不同的实例对象和对象空间地址引用键值对,从而实现多例模式。通过类字典判断实例对象是否创建,节省创建的成本。
2)、多例模式测试过程
当创建相同的实例对象name="A11"时,程序首先在实例池中搜索cls._loaded.get(name),若存在则直接返回已创建的实例对象空间。多例模式完美的实现了不同访问对象具体不同的实例化对象地址。
多例模式实例 正在创建访问对象 A11 <__main__.Solution object at 0x000001C105AA5EC8> 初始化init A11 10 解析完成finish A11 已经存在访问对象 A11 <__main__.Solution object at 0x000001C105AA5EC8> 初始化init A11 10 解析完成finish A11 正在创建访问对象 A12 <__main__.Solution object at 0x000001C105AA5F88> 初始化init A12 20 解析完成finish A12 True A11 A11 A12
3)、多例模式下缓冲机制的实现
进一步优化多例模式初始化过程,比如读取文件或者数据库时仅进行一次初始化加载。
class Solution: ##定义类实例化对象字典,即不同的实例对象对应不同的对象空间地址引用 _loaded = {} def __new__(cls, name,data,*args): if cls._loaded.get(name) is not None: client = cls._loaded.get(name) print(f"已经存在访问对象 {name}") print(client) return client print(f"正在创建访问对象 {name}") # 把类属性中保存的对象引用返回给python的解释器 client = super().__new__(cls) print(client) # 为该类实例name添加一个空间对象地址引用 cls._loaded[name] = client client._init_db(name,data) return client def _init_db(self,name,data): self.name = name self.data = data self.xml_load(self.data) def xml_load(self,data): print("初始化init",self.name,data) def Parser(self): print("解析完成finish",self.name) if __name__ == '__main__': print("多例模式实例-缓存") a = Solution("A11",10) a.Parser() b = Solution("A11",10) b.Parser() c = Solution("A12", 20) c.Parser() print(f"{a is b}") print(a.name) print(b.name) print(c.name)
多例模式实例 正在创建访问对象 A11 <__main__.Solution object at 0x0000024198989148> 初始化init A11 10 解析完成finish A11 已经存在访问对象 A11 <__main__.Solution object at 0x0000024198989148> 解析完成finish A11 正在创建访问对象 A12 <__main__.Solution object at 0x00000241989891C8> 初始化init A12 20 解析完成finish A12 True A11 A11 A12
注:多例模式下多个实例化对象均只进行一次初始化过程。
重写__new__方法中每个实例对象创建后绑定初始化_init_db()方法执行一次,后面遇到同一个实例对象将不会发生什么,直接返回已创建的实例对象。从测试结果来看,创建相同的实例对象name="A11"时,第二次将略过初始化数据加载过程,很好的实现了缓存机制。
__new__方法总结
本文结合项目背景详细介绍了__new__方法实现单例模式和多例模式以及缓存机制的实现!
1、__new__ 方法是在类创建实例的时候自动调用的。
2、 实例是通过类里面的 __ new __ 方法是在类创建出来的。
3、 先调用__new__ 方法创建实例,再调用 __ init __方法初始化实例。
4、 __new__ 方法,后面的括号里面的cls代表的是类本身。
5、__new__ 方法,判断类属性为空就去开辟空间,否则复用原来的地址。
更多的特殊方法比如1、自我描述方法:__repr__2、析构方法:__del__ 3、列出对象所有属性(包括方法)名:__dir__4、__dict__属性:查看对象内部所有属性名和属性值组成的字典5、__getattr____setattr__等。
当然还有metaclass类的__new__方法,可以动态修改程序中的一批类,这个功能在开发一些基础性的框架时非常有用,可以使用metaclass为某一批需要通用功能的类添加方法,若有合适实例场景后续分享。
위 내용은 Python에서 __new__ 메소드의 역할을 자세히 설명하는 기사의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











PHP는 주로 절차 적 프로그래밍이지만 객체 지향 프로그래밍 (OOP)도 지원합니다. Python은 OOP, 기능 및 절차 프로그래밍을 포함한 다양한 패러다임을 지원합니다. PHP는 웹 개발에 적합하며 Python은 데이터 분석 및 기계 학습과 같은 다양한 응용 프로그램에 적합합니다.

PHP는 웹 개발 및 빠른 프로토 타이핑에 적합하며 Python은 데이터 과학 및 기계 학습에 적합합니다. 1.PHP는 간단한 구문과 함께 동적 웹 개발에 사용되며 빠른 개발에 적합합니다. 2. Python은 간결한 구문을 가지고 있으며 여러 분야에 적합하며 강력한 라이브러리 생태계가 있습니다.

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

VS 코드 확장은 악의적 인 코드 숨기기, 취약성 악용 및 합법적 인 확장으로 자위하는 등 악성 위험을 초래합니다. 악의적 인 확장을 식별하는 방법에는 게시자 확인, 주석 읽기, 코드 확인 및주의해서 설치가 포함됩니다. 보안 조치에는 보안 인식, 좋은 습관, 정기적 인 업데이트 및 바이러스 백신 소프트웨어도 포함됩니다.

VS 코드는 파이썬을 작성하는 데 사용될 수 있으며 파이썬 애플리케이션을 개발하기에 이상적인 도구가되는 많은 기능을 제공합니다. 사용자는 다음을 수행 할 수 있습니다. Python 확장 기능을 설치하여 코드 완료, 구문 강조 및 디버깅과 같은 기능을 얻습니다. 디버거를 사용하여 코드를 단계별로 추적하고 오류를 찾아 수정하십시오. 버전 제어를 위해 git을 통합합니다. 코드 서식 도구를 사용하여 코드 일관성을 유지하십시오. 라인 도구를 사용하여 잠재적 인 문제를 미리 발견하십시오.

VS 코드는 Windows 8에서 실행될 수 있지만 경험은 크지 않을 수 있습니다. 먼저 시스템이 최신 패치로 업데이트되었는지 확인한 다음 시스템 아키텍처와 일치하는 VS 코드 설치 패키지를 다운로드하여 프롬프트대로 설치하십시오. 설치 후 일부 확장은 Windows 8과 호환되지 않을 수 있으며 대체 확장을 찾거나 가상 시스템에서 새로운 Windows 시스템을 사용해야합니다. 필요한 연장을 설치하여 제대로 작동하는지 확인하십시오. Windows 8에서는 VS 코드가 가능하지만 더 나은 개발 경험과 보안을 위해 새로운 Windows 시스템으로 업그레이드하는 것이 좋습니다.

vs 코드에서는 다음 단계를 통해 터미널에서 프로그램을 실행할 수 있습니다. 코드를 준비하고 통합 터미널을 열어 코드 디렉토리가 터미널 작업 디렉토리와 일치하는지 확인하십시오. 프로그래밍 언어 (예 : Python의 Python Your_file_name.py)에 따라 실행 명령을 선택하여 성공적으로 실행되는지 여부를 확인하고 오류를 해결하십시오. 디버거를 사용하여 디버깅 효율을 향상시킵니다.

PHP는 1994 년에 시작되었으며 Rasmuslerdorf에 의해 개발되었습니다. 원래 웹 사이트 방문자를 추적하는 데 사용되었으며 점차 서버 측 스크립팅 언어로 진화했으며 웹 개발에 널리 사용되었습니다. Python은 1980 년대 후반 Guidovan Rossum에 의해 개발되었으며 1991 년에 처음 출시되었습니다. 코드 가독성과 단순성을 강조하며 과학 컴퓨팅, 데이터 분석 및 기타 분야에 적합합니다.
