답변:
AFAIK, len
는이 점에서 특별하며 역사적 뿌리를 가지고 있습니다.
파이썬은 왜 일부 기능 (예 : list.index ())에 메서드를 사용하고 다른 기능 (예 : len (list))에 대해 사용합니까?
주된 이유는 역사입니다. 함수는 유형 그룹에 대해 일반적이고 메소드가 전혀없는 객체 (예 : 튜플)에서도 작동하도록 의도 된 작업에 사용되었습니다. 또한 Python의 기능적 기능 (map (), apply () 등)을 사용할 때 객체의 비정질 컬렉션에 쉽게 적용 할 수있는 함수를 갖는 것이 편리합니다.
실제로 len (), max (), min ()을 내장 함수로 구현하는 것은 실제로 각 유형의 메소드로 구현하는 것보다 코드가 적습니다. 개별 사례에 대해 고민 할 수 있지만 Python의 일부이며 지금 그러한 근본적인 변경을하기에는 너무 늦었습니다. 대규모 코드 손상을 방지하려면 함수를 유지해야합니다.
다른 "마법의 방법"(실제로는 특수 방법 이라고 함) Python 민속학에서 )은 많은 의미가 있으며 유사한 기능이 다른 언어에 존재합니다. 특수 구문을 사용할 때 암시 적으로 호출되는 코드에 주로 사용됩니다.
예를 들면 :
등등...
Zen of Python에서 :
모호함에도 불구하고 추측하려는 유혹을 거부하십시오.
이를 수행하는 분명한 방법은 하나, 바람직하게는 하나만 있어야합니다.
사용자 지정 방법으로, 개발자는 다른 방법 이름처럼 자유롭게 선택할 것 - 이것은 이유 중 하나입니다 getLength()
, length()
, getlength()
또는 무엇이든지 있습니다. Python은 공통 함수를 len()
사용할 수 있도록 엄격한 이름 지정을 적용 합니다.
많은 유형의 객체에 공통적 인 모든 작업은 __nonzero__
, __len__
또는 같은 매직 메서드에 배치됩니다 __repr__
. 하지만 대부분 선택 사항입니다.
연산자 오버로딩은 매직 메서드 (예 :)로도 수행 __le__
되므로 다른 일반적인 작업에도 사용하는 것이 좋습니다.
파이썬은 "마법의 방법" 이라는 단어를 사용합니다. 그 방법은 실제로 당신의 프로그램을 위해 마법을 수행하기 때문입니다. Python의 매직 메서드를 사용하는 가장 큰 장점 중 하나는 객체가 내장 유형처럼 동작하도록 만드는 간단한 방법을 제공한다는 것입니다. 즉, 기본 연산자를 수행하는 추악하고 직관에 반하는 비표준 방식을 피할 수 있습니다.
다음 예를 고려하십시오.
dict1 = {1 : "ABC"}
dict2 = {2 : "EFG"}
dict1 + dict2
Traceback (most recent call last):
File "python", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'dict' and 'dict'
사전 유형이 추가를 지원하지 않기 때문에 오류가 발생합니다. 이제 사전 클래스를 확장하고 "__add__" 매직 메서드를 추가해 보겠습니다 .
class AddableDict(dict):
def __add__(self, otherObj):
self.update(otherObj)
return AddableDict(self)
dict1 = AddableDict({1 : "ABC"})
dict2 = AddableDict({2 : "EFG"})
print (dict1 + dict2)
이제 다음과 같은 출력을 제공합니다.
{1: 'ABC', 2: 'EFG'}
따라서이 방법을 추가하면 갑자기 마술이 일어나고 이전에 받았던 오류가 사라졌습니다.
나는 그것이 당신에게 일을 분명히하기를 바랍니다. 자세한 내용은 다음을 참조하십시오.
파이썬의 마법 방법에 대한 가이드 (Rafe Kettler, 2012)
이러한 함수 중 일부는 단일 메서드가 구현할 수있는 것 이상을 수행합니다 (슈퍼 클래스의 추상 메서드없이). 예를 들어 다음 bool()
과 같이 작동합니다.
def bool(obj):
if hasattr(obj, '__nonzero__'):
return bool(obj.__nonzero__())
elif hasattr(obj, '__len__'):
if obj.__len__():
return True
else:
return False
return True
또한 100 % 확신 할 수 있습니다. bool()
항상 True 또는 False를 반환 . 만약 당신이 방법에 의존한다면 당신은 당신이 무엇을 되 찾을 지 완전히 확신 할 수 없습니다.
상대적으로 복잡한 구현 (기본 매직 메서드보다 더 복잡 할 가능성이있는 것보다 더 복잡함)이있는 다른 함수는 iter()
및 cmp()
, 모든 속성 메서드 ( getattr
, setattr
및 delattr
)입니다. int
강압을 수행 할 때 매직 메서드에 액세스하는 것과 같은 것 (를 구현할 수 있음 __int__
)도 있지만 유형으로서의 이중 의무를 수행합니다. len(obj)
실제로는 .NET과 전혀 다르지 않다고 생각하는 경우입니다 obj.__len__()
.
hasattr()
사용 하고 대신에 그냥 말할 것이지만 그것들은 문체 일뿐입니다. try:
except AttributeError:
if obj.__len__(): return True else: return False
return obj.__len__() > 0
bool(x)
참조 x.__nonzero__()
)에서는 방법이 작동하지 않습니다. bool 인스턴스에는 메서드 __nonzero__()
가 있으며 obj가 bool이면 코드가 계속 자신을 호출합니다. 아마도 bool(obj.__bool__())
당신이 치료 한 것과 같은 방식으로 치료를 받아야 __len__
합니까? (아니면이 코드가 실제로 Python 3에서 작동합니까?)
len(x)
및 x.__len__()
전 길이에 대한 초과 OverflowError 올릴이다 sys.maxsize
일반적 유형 파이썬 구현되지 후자있다. 그것은 기능 이라기보다는 버그에 가깝습니다. (예를 들어, 파이썬 3.2의 범위 객체는 대부분 임의로 큰 범위를 처리 할 수 있지만, len
그것들과 함께 사용 __len__
하면 실패 할 수 있습니다. 하지만 그것들은 파이썬이 아닌 C로 구현 되었기 때문에 실패합니다)
그 이유는 대부분 역사적이지만 파이썬 len
에는 적절한 메서드 대신 함수를 사용하는 몇 가지 특이점 이 있습니다.
파이썬에서 일부 작업은 예를 들어 방법으로 구현 list.index
하고 dict.append
다른 사람이 예를 들어, callables과 마법 방법으로 구현하는 동안, str
및 iter
과 reversed
. 두 그룹은 충분히 다르므로 다른 접근 방식이 정당합니다.
str
, int
친구는 유형입니다. 생성자를 호출하는 것이 더 합리적입니다.iter
호출 __getitem__
할 __iter__
수 있으며 메서드 호출에 맞지 않는 추가 인수를 지원합니다. 같은 이유로 최신 버전의 Python에서 it.next()
로 변경되었습니다 next(it)
. 더 합리적입니다.__iter__
과는 __next__
- 그것은이라고 for
루프. 일관성을 위해 함수가 더 좋습니다. 그리고 특정 최적화에 더 적합합니다.repr
같은 역할을 str
한다. str(x)
대 갖는 x.repr()
것은 혼란 스러울 것입니다.isinstance
.getattr(x, 'a')
일을하는 또 다른 방법입니다 x.a
및 getattr
상기 자질의 많은 주.저는 개인적으로 첫 번째 그룹을 방법과 같고 두 번째 그룹을 운영자와 같이 부릅니다. 그다지 좋은 구별은 아니지만 어떻게 든 도움이되기를 바랍니다.
이 말 len
은 두 번째 그룹에 정확히 맞지 않습니다. 거의 모든 것보다 훨씬 일반적이라는 유일한 차이점을 제외하면 첫 번째 작업에 더 가깝습니다. 그러나 그것이하는 유일한 일은를 호출하는 것입니다 __len__
. 그리고 그것은 L.index
. 그러나 몇 가지 차이점이 있습니다. 예를 들어, __len__
와 같은 다른 기능의 구현을 위해 호출 될 수 있습니다 bool
. 메소드가 호출 되면 완전히 다른 작업을 수행 하는 사용자 정의 메소드로 len
중단 될 수 있습니다 .bool(x)
len
요컨대, 클래스가 구현할 수있는 매우 일반적인 기능 집합이 있으며, 연산자를 통해 액세스 할 수 있고, 특수 함수 (일반적으로 연산자가 수행하는 것보다 더 많은 작업을 수행함), 객체 생성 중에 액세스 할 수 있습니다. 몇 가지 공통된 특성을 공유하십시오. 나머지는 모두 방법입니다. 그리고 len
그 규칙에 대한 약간의 예외입니다.
위의 두 게시물에 추가 할 내용이 많지 않지만 모든 "마법"기능은 실제로 마법이 아닙니다. 인터프리터가 시작될 때 암시 적으로 / 자동으로 가져 오는 __ builtins__ 모듈의 일부입니다. 즉 :
from __builtins__ import *
프로그램이 시작되기 전에 매번 발생합니다.
나는 항상 파이썬이 대화 형 쉘에 대해서만이 작업을 수행하고 필요한 빌트인에서 다양한 부분을 가져 오기 위해 스크립트를 필요로하는 것이 더 정확할 것이라고 생각했습니다. 또한 아마도 다른 __ main__ 처리는 쉘 대 대화 형에서 좋을 것입니다. 어쨌든 모든 기능을 확인하고 기능이 없으면 어떤 것인지 확인하십시오.
dir (__builtins__)
...
del __builtins__
len()
하거나reversed()
적용되는 것이지만append()
시퀀스에만 적용되는 것과 같은 방법입니다 .