2011-05-05 6 views
10

동시에 정적 인 인스턴스와 인스턴스가되도록 Python 메소드를 정의 할 수 있습니까? 뭔가 같이 : 그래서Python의 정적 및 인스턴스 메소드

class C(object): 
    @staticmethod 
    def a(self, arg1): 
     if self: 
      blah 
     blah 

내가 모두를 호출 할 수 있습니다 :

C.a(arg1) 
C().a(arg1) 

목적은 논리의 두 세트를 실행할 수 있도록한다. 인스턴스 메서드로 액세스하면 인스턴스 변수를 사용하고 작업을 수행합니다. 정적 메소드로 액세스 할 경우에는 액세스하지 않습니다.

+2

시도해 보셨습니까? –

+0

http://stackoverflow.com/questions/5812537/can-i-have-a-method-of-a-class-which-can-be-used-as-a-staticmethod-or-instance-me은 분명합니다. 재미있는. 나는 그것을하기의 적은 "해킹"방법이 있는지 다만 생각해보고 있었다 – xster

답변

17
import functools 

class static_or_instance(object): 
    def __init__(self, func): 
    self.func = func 

    def __get__(self, instance, owner): 
    return functools.partial(self.func, instance) 

class C(object): 
    @static_or_instance 
    def a(self, arg): 
    if self is None: 
     print "called without self:", arg 
    else: 
     print "called with self:", arg 

C.a(42) 
C().a(3) 
+4

매우 근사합니다. 하지만 나는 그것을 싫어 : D –

+0

당신이 해냈어. 네가 해냈다 니 믿을 수가 없어! – jathanism

+0

매우 근사합니다. – Haranadh

2

아니요. self은 그 방법 내에서 무엇을 의미할까요?

1

매개 변수를 a()으로 제거하면 코드가 작동합니다. C().a(arg1)으로 호출하면 인스턴스가 무시됩니다.

하지만이 메서드는 정적 메서드와 인스턴스를받는 메서드로 작동해야합니다. 당신은 두 가지 방법 모두 가질 수 없습니다.

+0

그러나 그 때 그것은 정상적인 정적 방법이 될 것입니다. 인스턴스 메서드로 사용될 경우 다른 논리 집합을 실행하고 자체 액세스 할 수있게하고 싶습니다. – xster

+1

메서드 내에서 사용할 변수를 더 잘 전달할 수 있습니다. 그런 다음 인스턴스 변수인지 여부는 상관하지 않습니다. – jathanism

4

formencode에는 classinstancemethod 데코레이터가 있으며 원하는 것을 수행합니다. 그것은 2 개 인자 (selfcls, 그 중 하나가 호출 문맥에 따라 None을 전달받을 수있다)

formencode/declarative.py

class classinstancemethod(object): 
    """ 
    Acts like a class method when called from a class, like an 
    instance method when called by an instance. The method should 
    take two arguments, 'self' and 'cls'; one of these will be None 
    depending on how the method was called. 
    """ 

    def __init__(self, func): 
     self.func = func 

    def __get__(self, obj, type=None): 
     return _methodwrapper(self.func, obj=obj, type=type) 

class _methodwrapper(object): 

    def __init__(self, func, obj, type): 
     self.func = func 
     self.obj = obj 
     self.type = type 

    def __call__(self, *args, **kw): 
     assert not kw.has_key('self') and not kw.has_key('cls'), (
      "You cannot use 'self' or 'cls' arguments to a " 
      "classinstancemethod") 
     return self.func(*((self.obj, self.type) + args), **kw) 

    def __repr__(self): 
     if self.obj is None: 
      return ('<bound class method %s.%s>' 
        % (self.type.__name__, self.func.func_name)) 
     else: 
      return ('<bound method %s.%s of %r>' 
        % (self.type.__name__, self.func.func_name, self.obj)) 

샘플 사용에서 드러내을 가지고 방법을 필요로

class A(object): 
    data = 5 

    @classinstancemethod 
    def print_(self=None, cls=None): 
     ctx = self or cls 
     print ctx.data 


>>> A.print_() 
5 
>>> a = A() 
>>> a.data = 4 
>>> a.print_() 
4