source

Python 함수 속성 - 사용 및 남용

manysource 2022. 11. 24. 21:42

Python 함수 속성 - 사용 및 남용

이 기능을 아는 사람은 많지 않지만 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

Python에서 이 기능의 사용 및 남용은 무엇입니까?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;
}

Python에서도 비슷한 기능을 구현할 수 있습니다.

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

함수의 속성을 사용하여 이미 계산된 값을 캐싱할 수 있습니다.또, 이 어프로치를 일반화하는 범용 데코레이터를 사용할 수도 있습니다.동시성 문제 및 이러한 기능의 부작용에 유의하십시오!

나는 항상 이것이 가능한 유일한 이유는 문서 문자열이나 다른 것들을 넣을 수 있는 논리적인 장소가 있기 때문이라고 생각했다.만약 내가 어떤 생산 코드에 사용한다면, 누가 읽는지 혼란스러울 거라는 걸 알아.

언급URL : https://stackoverflow.com/questions/338101/python-function-attributes-uses-and-abuses