如果一个变量指的是一个函数或一个类的方法,我怎么能找到它是哪一个,并得到了类类型的情况下,特别是当类仍然被宣布为在给定的例子一个类的方法.
例如.
def get_info(function_or_method):
print function_or_method
class Foo(object):
def __init__(self):
pass
get_info(__init__)
def bar():
pass
get_info(bar)
Run Code Online (Sandbox Code Playgroud)
在David和JF Sebastian的前两个回复之后更新问题
为了再次强调JF Sebastian提到的一个观点,我希望能够在类中声明函数时区分它(当我得到的类型是函数时而不是绑定或未绑定的方法).即.在第一次调用get_info(__init__)发生的地方,我希望能够检测到它的方法被声明为类的一部分.
这个问题出现了,因为我在它周围放了一个装饰器,它获得了init函数的句柄,我实际上无法弄清楚方法是在一个类中声明还是作为一个独立的函数
我一直在寻找 的源代码peewee,特别Model是该update函数:https://github.com/coleifer/peewee/blob/a33e8ccbd5b1e49f0a781d38d40eb5e8f344eee5/peewee.py#L4718
我不喜欢这样的事实:如果语句未与子句正确耦合,则任何更新操作都会影响模型中的每一行,可以从行实例调用此方法where。因此,我想找到某种方法来禁止从模型实例调用此类方法。
一些谷歌搜索让我相信这可能相当困难。delattr从__init__似乎没有工作。从 update 函数运行isclass(self)总是返回 True,因为当我们在类方法内部时,我们实际上是类而不是实例。
有什么建议么?
我正在尝试创建一个可以在类上定义的装饰器,并装饰其中定义的所有内容。首先让我展示一下我已经基于其他 SO 答案得到的设置:
import inspect
# https://stackoverflow.com/a/18421294/577669
def log(func):
def wrapped(*args, **kwargs):
try:
print("Entering: [%s]" % func)
try:
# https://stackoverflow.com/questions/19227724/check-if-a-function-uses-classmethod
if inspect.ismethod(func) and func.__self__: # class method
return func(*args[1:], **kwargs)
if inspect.isdatadescriptor(func):
return func.fget(args[0])
return func(*args, **kwargs)
except Exception as e:
print('Exception in %s : (%s) %s' % (func, e.__class__.__name__, e))
finally:
print("Exiting: [%s]" % func)
return wrapped
class trace(object):
def __call__(self, cls): # instance, owner):
for name, m in inspect.getmembers(cls, lambda x: inspect.ismethod(x) or inspect.isfunction(x)):
setattr(cls, name, log(m))
for …Run Code Online (Sandbox Code Playgroud) 例如,请考虑以下情况:
class FooMeta(type):
def __len__(cls):
return 9000
class GoodBar(metaclass=FooMeta):
def __len__(self):
return 9001
class BadBar(metaclass=FooMeta):
@classmethod
def __len__(cls):
return 9002
len(GoodBar) -> 9000
len(GoodBar()) -> 9001
GoodBar.__len__() -> TypeError (missing 1 required positional argument)
GoodBar().__len__() -> 9001
len(BadBar) -> 9000 (!!!)
len(BadBar()) -> 9002
BadBar.__len__() -> 9002
BadBar().__len__() -> 9002
Run Code Online (Sandbox Code Playgroud)
问题在于len(BadBar)返回 9000 而不是 9002,这是预期的行为。
这种行为(在某种程度上)记录在Python 数据模型 - 特殊方法查找中,但它没有提到任何有关类方法的内容,而且我并不真正理解与@classmethod装饰器的交互。
除了明显的元类解决方案(即替换/扩展FooMeta)之外,是否有一种方法可以覆盖或扩展元类函数,以便len(BadBar) -> 9002?
为了澄清,在我的特定用例中,我无法编辑元类,并且我不想对其进行子类化和/或创建我自己的元类,除非这是唯一可能的方法。
python ×4
class-method ×1
cpython ×1
decorator ×1
metaclass ×1
overriding ×1
peewee ×1
reflection ×1