이 기능을 잘 아는 사람은 많지 않지만 Python의 함수 (및 메소드)는 속성 을 가질 수 있습니다 . 보다:
>>> def foo(x):
... pass
...
>>> foo.score = 10
>>> dir(foo)
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name', 'score']
>>> foo.score
10
>>> foo.score += 1
>>> foo.score
11
파이썬에서이 기능의 가능한 사용과 남용은 무엇입니까? 내가 아는 한 가지 좋은 사용법은 구문 규칙을 메소드와 연관시키기 위해 PLY 의 docstring 사용입니다. 그러나 사용자 정의 속성은 어떻습니까? 그것들을 사용해야 할 좋은 이유가 있습니까?
답변
일반적으로 함수 속성을 주석의 저장소로 사용합니다. C # 스타일로 작성하고 싶다고 가정하십시오 (특정 메소드가 웹 서비스 인터페이스의 일부 여야 함을 나타냄)
class Foo(WebService):
@webmethod
def bar(self, arg1, arg2):
...
그런 다음 정의 할 수 있습니다
def webmethod(func):
func.is_webmethod = True
return func
그런 다음 웹 서비스 호출이 도착하면 메소드를 찾고 기본 함수에 is_webmethod 속성이 있는지 확인하고 (실제 값은 관련이 없음) 메소드가 없거나 웹을 통해 호출 될 의도가 아닌 경우 서비스를 거부합니다.
답변
함수의 정적 변수로 사용했습니다. 예를 들어 다음과 같은 C 코드가 제공됩니다.
int fn(int i)
{
static f = 1;
f += i;
return f;
}
파이썬에서 비슷하게 함수를 구현할 수 있습니다.
def fn(i):
fn.f += i
return fn.f
fn.f = 1
이것은 스펙트럼의 “구슬”끝에 빠질 것입니다.
답변
JavaScript 방식으로 객체를 수행 할 수 있습니다 … 의미가 없지만 작동합니다.)
>>> def FakeObject():
... def test():
... print "foo"
... FakeObject.test = test
... return FakeObject
>>> x = FakeObject()
>>> x.test()
foo
답변
나는 그것들을 조금만 사용하지만 매우 편리 할 수 있습니다.
def log(msg):
log.logfile.write(msg)
이제 log
모듈 전체에서 사용할 수 있으며 간단히 설정하여 출력을 리디렉션 할 수 있습니다 log.logfile
. 그것을 달성하는 많은 방법이 많이 있지만, 이것은 가볍고 흙이 간단합니다. 처음했을 때 우스운 냄새가 났지만 전역 logfile
변수 보다 냄새가 더 좋다고 믿었습니다 .
답변
함수 속성을 사용하여 코드와 관련 데이터를 함께 감싸는 간단한 클로저를 작성할 수 있습니다.
#!/usr/bin/env python
SW_DELTA = 0
SW_MARK = 1
SW_BASE = 2
def stopwatch():
import time
def _sw( action = SW_DELTA ):
if action == SW_DELTA:
return time.time() - _sw._time
elif action == SW_MARK:
_sw._time = time.time()
return _sw._time
elif action == SW_BASE:
return _sw._time
else:
raise NotImplementedError
_sw._time = time.time() # time of creation
return _sw
# test code
sw=stopwatch()
sw2=stopwatch()
import os
os.system("sleep 1")
print sw() # defaults to "SW_DELTA"
sw( SW_MARK )
os.system("sleep 2")
print sw()
print sw2()
1.00934004784
2.00644397736
3.01593494415
답변
이 도우미 데코레이터를 만들어 기능 속성을 쉽게 설정할 수 있습니다.
def with_attrs(**func_attrs):
"""Set attributes in the decorated function, at definition time.
Only accepts keyword arguments.
E.g.:
@with_attrs(counter=0, something='boing')
def count_it():
count_it.counter += 1
print count_it.counter
print count_it.something
# Out:
# >>> 0
# >>> 'boing'
"""
def attr_decorator(fn):
@wraps(fn)
def wrapper(*args, **kwargs):
return fn(*args, **kwargs)
for attr, value in func_attrs.iteritems():
setattr(wrapper, attr, value)
return wrapper
return attr_decorator
유스 케이스는 팩토리 콜렉션을 작성하고 함수 메타 레벨에서 작성할 수있는 데이터 유형을 조회하는 것입니다.
예를 들어 (매우 바보 같은) :
@with_attrs(datatype=list)
def factory1():
return [1, 2, 3]
@with_attrs(datatype=SomeClass)
def factory2():
return SomeClass()
factories = [factory1, factory2]
def create(datatype):
for f in factories:
if f.datatype == datatype:
return f()
return None
답변
때로는 이미 계산 된 값을 캐싱하기 위해 함수의 속성을 사용합니다. 이 방법을 일반화하는 일반 데코레이터를 사용할 수도 있습니다. 동시성 문제와 이러한 기능의 부작용에주의하십시오!