Python의 매직 설명자
소개
설명자(descriptor)는 Python 언어에서 심오하지만 중요한 흑마술입니다. Python 언어의 핵심으로 널리 사용됩니다. 설명자에 능숙하면 Python 추가됩니다. 프로그래머의 도구 상자에 속임수를 쓰세요. 이 글에서는 디스크립터의 정의와 몇 가지 일반적인 시나리오에 대해 이야기하고, 글 마지막에 , __getattr
, __getattribute__
세 가지 __getitem__
매직 메소드를 추가하겠습니다. 속성 액세스를 포함합니다.
descr__get__(self, obj, objtype=None) --> value
descr.__set__(self, obj, value) --> None
descr.__delete__(self, obj) --> None
로그인 후 복사
descr__get__(self, obj, objtype=None) --> value descr.__set__(self, obj, value) --> None descr.__delete__(self, obj) --> None
(객체 속성)가 위의 세 가지 메서드 중 하나를 정의하는 한 이 클래스는 설명자 클래스라고 부를 수 있습니다. object attribute
클래스를 만들고 RevealAcess
메서드를 구현합니다. 이제 이 클래스를 설명자 클래스라고 부를 수 있습니다. __get__
class RevealAccess(object): def __get__(self, obj, objtype): print('self in RevealAccess: {}'.format(self)) print('self: {}\nobj: {}\nobjtype: {}'.format(self, obj, objtype)) class MyClass(object): x = RevealAccess() def test(self): print('self in MyClass: {}'.format(self))
EX1 인스턴스 속성
다음으로 메소드의 각 매개변수의 의미를 살펴보겠습니다. 다음 예에서 __get__
는 RevealAccess 클래스 인스턴스 x, self
는 MyClass 클래스의 인스턴스 m이고, obj
는 이름에서 알 수 있듯이 MyClass 클래스 자체입니다. 출력 문에서 볼 수 있듯이 objtype
액세스 설명자 m.x
는 x
메서드를 호출합니다. __get__
>>> m = MyClass() >>> m.test() self in MyClass: <__main__.MyClass object at 0x7f19d4e42160> >>> m.x self in RevealAccess: <__main__.RevealAccess object at 0x7f19d4e420f0> self: <__main__.RevealAccess object at 0x7f19d4e420f0> obj: <__main__.MyClass object at 0x7f19d4e42160> objtype: <class '__main__.MyClass'>
EX2 클래스 속성
속성이 클래스를 통해 직접 액세스되는 경우 x
연결은 직접 None이므로 이해하기 쉽습니다. , MyClass 인스턴스가 존재하지 않기 때문입니다. obj
>>> MyClass.x self in RevealAccess: <__main__.RevealAccess object at 0x7f53651070f0> self: <__main__.RevealAccess object at 0x7f53651070f0> obj: None objtype: <class '__main__.MyClass'>
-
에 액세스하면 기본 클래스 객체의 __getattribute__ 메서드가 실제로 호출됩니다. 이 메서드에서는 obj.d가
实例属性
로 변환됩니다.type(obj).__dict__['d'].__get__(obj, type(obj))
에 액세스하면 cls.d를
类属性
로 변환하는 메타클래스 유형의 __getattribute__ 메서드를 호출하는 것과 같습니다. 여기서 __get__( )의 obj는 다음과 같습니다. 인스턴스가 없기 때문에 없음입니다.cls.__dict__['d'].__get__(None, cls)
매직 메소드에 대해 간단히 이야기해보겠습니다. 이 메소드는 객체의 속성에 접근할 때 무조건 호출됩니다. 자세한 내용은 __getattribute__
, __getattr
과 같습니다. 기사 마지막 부분에 추가 보충 자료를 작성하겠지만 지금은 자세히 다루지 않겠습니다. __getitem__
- 객체가 __get__() 및 __set__() 메서드를 모두 정의하는 경우 , 이 설명자를
이라고 합니다.
data descriptor
- 객체가 __get__() 메서드만 정의하는 경우 이 설명자를
이라고 합니다.
non-data descriptor
- 데이터 설명자
- 인스턴스 사전
- 비데이터 설명자
- __getattr__()
data descriptor > instance dict > non-data descriptor > __getattr__()
과 data descriptor->d
가 인스턴스 객체 obj에 나타나면 instance attribute->d
가 obj.d
속성에 액세스할 때 데이터 설명자의 우선순위가 더 높기 때문에 Python은 d
을 호출합니다. 대신 obj.__dict__['d']를 호출하는 대신. 그러나 설명자가 데이터 설명자가 아닌 경우 Python은 type(obj).__dict__['d'].__get__(obj, type(obj))
을 호출합니다. obj.__dict__['d']
property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
class Account(object): def __init__(self): self._acct_num = None def get_acct_num(self): return self._acct_num def set_acct_num(self, value): self._acct_num = value def del_acct_num(self): del self._acct_num acct_num = property(get_acct_num, set_acct_num, del_acct_num, '_acct_num property.')
>>> acct = Account() >>> acct.acct_num = 1000 >>> acct.acct_num 1000
데코레이터도 제공합니다. 속성 개체에는 해당 데코레이팅된 함수의 접근자 함수를 통해 속성의 복사본을 만드는 데 사용할 수 있는 getter, setter 및 delete 데코레이터 메서드가 있습니다. @property
class Account(object): def __init__(self): self._acct_num = None @property # the _acct_num property. the decorator creates a read-only property def acct_num(self): return self._acct_num @acct_num.setter # the _acct_num property setter makes the property writeable def set_acct_num(self, value): self._acct_num = value @acct_num.deleter def del_acct_num(self): del self._acct_num
class Person(object): def addProperty(self, attribute): # create local setter and getter with a particular attribute name getter = lambda self: self._getProperty(attribute) setter = lambda self, value: self._setProperty(attribute, value) # construct property attribute and add it to the class setattr(self.__class__, attribute, property(fget=getter, \ fset=setter, \ doc="Auto-generated method")) def _setProperty(self, attribute, value): print("Setting: {} = {}".format(attribute, value)) setattr(self, '_' + attribute, value.title()) def _getProperty(self, attribute): print("Getting: {}".format(attribute)) return getattr(self, '_' + attribute)
및 @staticmethod
. 먼저 아래 표를 살펴보겠습니다. @classmethod
Transformation | Called from an Object | Called from a Class |
---|---|---|
function | f(obj, *args) | f(*args) |
staticmethod | f(*args) | f(*args) |
classmethod | f(type(obj), *args) | f(klass, *args) |
静态方法
对于静态方法f
。c.f
和C.f
是等价的,都是直接查询object.__getattribute__(c, ‘f’)
或者object.__getattribute__(C, ’f‘)
。静态方法一个明显的特征就是没有self
变量。
静态方法有什么用呢?假设有一个处理专门数据的容器类,它提供了一些方法来求平均数,中位数等统计数据方式,这些方法都是要依赖于相应的数据的。但是类中可能还有一些方法,并不依赖这些数据,这个时候我们可以将这些方法声明为静态方法,同时这也可以提高代码的可读性。
使用非数据描述符来模拟一下静态方法的实现:
class StaticMethod(object): def __init__(self, f): self.f = f def __get__(self, obj, objtype=None): return self.f
我们来应用一下:
class MyClass(object): @StaticMethod def get_x(x): return x print(MyClass.get_x(100)) # output: 100
类方法
Python的@classmethod
和@staticmethod
的用法有些类似,但是还是有些不同,当某些方法只需要得到类的引用
而不关心类中的相应的数据的时候就需要使用classmethod了。
使用非数据描述符来模拟一下类方法的实现:
class ClassMethod(object): def __init__(self, f): self.f = f def __get__(self, obj, klass=None): if klass is None: klass = type(obj) def newfunc(*args): return self.f(klass, *args) return newfunc
其他的魔术方法
首次接触Python魔术方法的时候,我也被__get__
, __getattribute__
, __getattr__
, __getitem__
之间的区别困扰到了,它们都是和属性访问相关的魔术方法,其中重写__getattr__
,__getitem__
来构造一个自己的集合类非常的常用,下面我们就通过一些例子来看一下它们的应用。
__getattr__
Python默认访问类/实例的某个属性都是通过__getattribute__
来调用的,__getattribute__
会被无条件调用,没有找到的话就会调用__getattr__
。如果我们要定制某个类,通常情况下我们不应该重写__getattribute__
,而是应该重写__getattr__
,很少看见重写__getattribute__
的情况。
从下面的输出可以看出,当一个属性通过__getattribute__
无法找到的时候会调用__getattr__
。
In [1]: class Test(object): ...: def __getattribute__(self, item): ...: print('call __getattribute__') ...: return super(Test, self).__getattribute__(item) ...: def __getattr__(self, item): ...: return 'call __getattr__' ...: In [2]: Test().a call __getattribute__ Out[2]: 'call __getattr__'
应用
对于默认的字典,Python只支持以obj['foo']
形式来访问,不支持obj.foo
的形式,我们可以通过重写__getattr__
让字典也支持obj['foo']
的访问形式,这是一个非常经典常用的用法:
class Storage(dict): """ A Storage object is like a dictionary except `obj.foo` can be used in addition to `obj['foo']`. """ def __getattr__(self, key): try: return self[key] except KeyError as k: raise AttributeError(k) def __setattr__(self, key, value): self[key] = value def __delattr__(self, key): try: del self[key] except KeyError as k: raise AttributeError(k) def __repr__(self): return '<Storage ' + dict.__repr__(self) + '>'
我们来使用一下我们自定义的加强版字典:
>>> s = Storage(a=1) >>> s['a'] 1 >>> s.a 1 >>> s.a = 2 >>> s['a'] 2 >>> del s.a >>> s.a ... AttributeError: 'a'
__getitem__
getitem用于通过下标[]
的形式来获取对象中的元素,下面我们通过重写__getitem__
来实现一个自己的list。
class MyList(object): def __init__(self, *args): self.numbers = args def __getitem__(self, item): return self.numbers[item] my_list = MyList(1, 2, 3, 4, 6, 5, 3) print my_list[2]
这个实现非常的简陋,不支持slice和step等功能,请读者自行改进,这里我就不重复了。
应用
下面是参考requests库中对于__getitem__
的一个使用,我们定制了一个忽略属性大小写的字典类。
程序有些复杂,我稍微解释一下:由于这里比较简单,没有使用描述符的需求,所以使用了@property
装饰器来代替,lower_keys
的功能是将实例字典
中的键全部转换成小写并且存储在字典self._lower_keys
中。重写了__getitem__
方法,以后我们访问某个属性首先会将键转换为小写的方式,然后并不会直接访问实例字典,而是会访问字典self._lower_keys
去查找。赋值/删除操作的时候由于实例字典会进行变更,为了保持self._lower_keys
和实例字典同步,首先清除self._lower_keys
的内容,以后我们重新查找键的时候再调用__getitem__
的时候会重新新建一个self._lower_keys
。
class CaseInsensitiveDict(dict): @property def lower_keys(self): if not hasattr(self, '_lower_keys') or not self._lower_keys: self._lower_keys = dict((k.lower(), k) for k in self.keys()) return self._lower_keys def _clear_lower_keys(self): if hasattr(self, '_lower_keys'): self._lower_keys.clear() def __contains__(self, key): return key.lower() in self.lower_keys def __getitem__(self, key): if key in self: return dict.__getitem__(self, self.lower_keys[key.lower()]) def __setitem__(self, key, value): dict.__setitem__(self, key, value) self._clear_lower_keys() def __delitem__(self, key): dict.__delitem__(self, key) self._lower_keys.clear() def get(self, key, default=None): if key in self: return self[key] else: return default
我们来调用一下这个类:
>>> d = CaseInsensitiveDict() >>> d['ziwenxie'] = 'ziwenxie' >>> d['ZiWenXie'] = 'ZiWenXie' >>> print(d) {'ZiWenXie': 'ziwenxie', 'ziwenxie': 'ziwenxie'} >>> print(d['ziwenxie']) ziwenxie # d['ZiWenXie'] => d['ziwenxie'] >>> print(d['ZiWenXie']) ziwenxie
위 내용은 Python의 매직 설명자의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

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

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

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

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

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

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

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

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

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

뜨거운 주제











깃털 통제의 열쇠는 점진적인 성격을 이해하는 것입니다. PS 자체는 그라디언트 곡선을 직접 제어하는 옵션을 제공하지 않지만 여러 깃털, 일치하는 마스크 및 미세 선택으로 반경 및 구배 소프트를 유연하게 조정하여 자연스럽게 전이 효과를 달성 할 수 있습니다.

이 기사는 MySQL 데이터베이스의 작동을 소개합니다. 먼저 MySQLworkBench 또는 명령 줄 클라이언트와 같은 MySQL 클라이언트를 설치해야합니다. 1. MySQL-Uroot-P 명령을 사용하여 서버에 연결하고 루트 계정 암호로 로그인하십시오. 2. CreateABase를 사용하여 데이터베이스를 작성하고 데이터베이스를 선택하십시오. 3. CreateTable을 사용하여 테이블을 만들고 필드 및 데이터 유형을 정의하십시오. 4. InsertInto를 사용하여 데이터를 삽입하고 데이터를 쿼리하고 업데이트를 통해 데이터를 업데이트하고 DELETE를 통해 데이터를 삭제하십시오. 이러한 단계를 마스터하고 일반적인 문제를 처리하는 법을 배우고 데이터베이스 성능을 최적화하면 MySQL을 효율적으로 사용할 수 있습니다.

MySQL에는 무료 커뮤니티 버전과 유료 엔터프라이즈 버전이 있습니다. 커뮤니티 버전은 무료로 사용 및 수정할 수 있지만 지원은 제한되어 있으며 안정성이 낮은 응용 프로그램에 적합하며 기술 기능이 강합니다. Enterprise Edition은 안정적이고 신뢰할 수있는 고성능 데이터베이스가 필요하고 지원 비용을 기꺼이 지불하는 응용 프로그램에 대한 포괄적 인 상업적 지원을 제공합니다. 버전을 선택할 때 고려 된 요소에는 응용 프로그램 중요도, 예산 책정 및 기술 기술이 포함됩니다. 완벽한 옵션은없고 가장 적합한 옵션 만 있으므로 특정 상황에 따라 신중하게 선택해야합니다.

PS 페더 링은 이미지 가장자리 블러 효과로, 가장자리 영역에서 픽셀의 가중 평균에 의해 달성됩니다. 깃털 반경을 설정하면 흐림 정도를 제어 할 수 있으며 값이 클수록 흐려집니다. 반경을 유연하게 조정하면 이미지와 요구에 따라 효과를 최적화 할 수 있습니다. 예를 들어, 캐릭터 사진을 처리 할 때 더 작은 반경을 사용하여 세부 사항을 유지하고 더 큰 반경을 사용하여 예술을 처리 할 때 흐릿한 느낌을줍니다. 그러나 반경이 너무 커서 가장자리 세부 사항을 쉽게 잃을 수 있으며 너무 작아 효과는 분명하지 않습니다. 깃털 효과는 이미지 해상도의 영향을받으며 이미지 이해 및 효과 파악에 따라 조정해야합니다.

PS 페더 링은 이미지 세부 사항 손실, 색상 포화 감소 및 노이즈 증가로 이어질 수 있습니다. 충격을 줄이려면 더 작은 깃털 반경을 사용하고 레이어를 복사 한 다음 깃털을 복사 한 다음 깃털 전후에 이미지 품질을 조심스럽게 비교하는 것이 좋습니다. 또한 깃털이 모든 경우에 적합하지는 않으며 때로는 마스크와 같은 도구가 이미지 가장자리를 처리하는 데 더 적합합니다.

MySQL 성능 최적화는 설치 구성, 인덱싱 및 쿼리 최적화, 모니터링 및 튜닝의 세 가지 측면에서 시작해야합니다. 1. 설치 후 innodb_buffer_pool_size 매개 변수와 같은 서버 구성에 따라 my.cnf 파일을 조정해야합니다. 2. 과도한 인덱스를 피하기 위해 적절한 색인을 작성하고 Execution 명령을 사용하여 실행 계획을 분석하는 것과 같은 쿼리 문을 최적화합니다. 3. MySQL의 자체 모니터링 도구 (showprocesslist, showstatus)를 사용하여 데이터베이스 건강을 모니터링하고 정기적으로 백업 및 데이터베이스를 구성하십시오. 이러한 단계를 지속적으로 최적화함으로써 MySQL 데이터베이스의 성능을 향상시킬 수 있습니다.

MySQL 데이터베이스 성능 최적화 안내서 리소스 집약적 응용 프로그램에서 MySQL 데이터베이스는 중요한 역할을 수행하며 대규모 트랜잭션 관리를 담당합니다. 그러나 응용 프로그램 규모가 확장됨에 따라 데이터베이스 성능 병목 현상은 종종 제약이됩니다. 이 기사는 일련의 효과적인 MySQL 성능 최적화 전략을 탐색하여 응용 프로그램이 고 부하에서 효율적이고 반응이 유지되도록합니다. 실제 사례를 결합하여 인덱싱, 쿼리 최적화, 데이터베이스 설계 및 캐싱과 같은 심층적 인 주요 기술을 설명합니다. 1. 데이터베이스 아키텍처 설계 및 최적화 된 데이터베이스 아키텍처는 MySQL 성능 최적화의 초석입니다. 몇 가지 핵심 원칙은 다음과 같습니다. 올바른 데이터 유형을 선택하고 요구 사항을 충족하는 가장 작은 데이터 유형을 선택하면 저장 공간을 절약 할 수있을뿐만 아니라 데이터 처리 속도를 향상시킬 수 있습니다.

MySQL 설치 실패에 대한 일반적인 이유 및 솔루션 : 1. 잘못된 사용자 이름 또는 비밀번호 또는 MySQL 서비스가 시작되지 않았으므로 사용자 이름과 비밀번호를 확인하고 서비스를 시작해야합니다. 2. 포트 충돌, MySQL 청취 포트를 변경하거나 포트 3306을 차지하는 프로그램을 닫아야합니다. 3. 종속성 라이브러리가 없으므로 시스템 패키지 관리자를 사용하여 필요한 종속성 라이브러리를 설치해야합니다. 4. 권한이 부족하면 Sudo 또는 관리자 권한을 사용하여 설치 프로그램을 실행해야합니다. 5. 잘못된 구성 파일, 구성이 올바른지 확인하려면 my.cnf 구성 파일을 확인해야합니다. 꾸준하고 신중하게 확인하는 것만으로 만 MySQL을 원활하게 설치할 수 있습니다.
