2014-02-06 3 views
4

Я хотел бы написать декоратор для метода класса python, который может определить, был ли метод вызван из контекста public или частного. Например, если следующий кодОпределение области/контекста вызова метода в python

def public_check_decorator(f): 
    def wrapper(self): 
     if self.f is `called publicly`: # <-- how do I make this line work correctly? 
      print 'called publicly' 
     else: 
      print 'called privately' 
     return f(self) 
    return wrapper 

class C(object): 
    @public_check_decorator 
    def public_method(self): 
     pass 

    def calls_public_method(self): 
     self.public_method() 

исполнение во время выполнения, в идеале выглядеть примерно так:

>>> c = C() 
>>> c.public_method() 
called publicly 

>>> c.calls_public_method() 
called privately 

Есть ли способ сделать это в Python? То есть, измените линию

if self.f is `called publicly`: # <-- how do I make this line work correctly? 

, чтобы дать желаемый результат?

+2

Просто из любопытства, зачем вам это нужно? – Blender

+1

как вам * определить * публичный? это вызов, вызываемый вне любой функции? называется глобальной функцией? что-то другое? Есть ли определенный стек, который вы определяете как публичную запись в функцию? – mhlester

+0

'c.public_method' такой же, как' self.public_method' в 'calls_public_method'. Итак, что именно вы пытаетесь проверить? – thefourtheye

ответ

0

Некоторые из них, похоже, пытаются плыть против тока «python». Это уместно?

Знаете ли вы о стандарте двойного осколка? Он делает методы «более частными»:

>>> class C(object): 
... def __hide_me(self): 
...  return 11 
... def public(self): 
...  return self.__hide_me() 
... 
>>> c = C() 
>>> c.__hide_me() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'C' object has no attribute '__hide_me' 
>>> c.public() 
11 
>>> c._C__hide_me() 
11 
>>> 

Это достаточно личное? И использование этой техники является питоновой.

+0

Двойное подчеркивание и название mangling - это не то, что я здесь. И я бы утверждал, что то, что я пытаюсь сделать, - это питонический по своей сути.Я хочу, чтобы метод класса с помощью другой функции влиял на поведение этого метода. Это то, что делают декораторы и метаклассы, и что делает их невероятно мощными (и действительно питоническими!). Мои комментарии к моему основному сообщению могут быть прочитаны, чтобы показаться, что я просто пытаюсь сделать метод только для личного доступа; это неправильное чтение, хотя это один из возможных вариантов использования. – kalefranz

0

Учитывая имя пакета решает, является ли функция вызывается из частного контекста или общественной один:

import inspect 
import re 


def run(): 
    package_name = '/my_package/' 
    p = re.match(r'^.*' + package_name, inspect.stack()[0].filename).group() 
    is_private_call = any(re.match(p, frame.filename) is not None for frame in inspect.stack()[1:]) 
    print(is_private_call) 

Попробуйте запустить внутри пакета, а затем из-за пределов упаковки !!! см. inspect.stack()

Смежные вопросы