嗨我有类似下面的东西.基本上我需要从定义中的实例方法使用的装饰器访问实例方法的类.
def decorator(view):
# do something that requires view's class
print view.im_class
return view
class ModelA(object):
@decorator
def a_method(self):
# do some stuff
pass
Run Code Online (Sandbox Code Playgroud)
代码原样给出
AttributeError: 'function' object has no attribute 'im_class'
我发现类似的问题/答案 - Python装饰器让函数忘记它属于一个类和Python装饰器中的Get类 - 但这些依赖于一种解决方法,它通过抢夺第一个参数在运行时抓取实例.在我的情况下,我将基于从其类中收集的信息调用该方法,因此我不能等待来电.
谢谢.
如何获得在Python中定义方法的类?
我想要以下示例打印" __main__.FooClass
":
class FooClass:
def foo_method(self):
print "foo"
class BarClass(FooClass):
pass
bar = BarClass()
print get_class_that_defined_method(bar.foo_method)
Run Code Online (Sandbox Code Playgroud) 给定方法的引用,有没有办法检查方法是否绑定到对象?你还可以访问它绑定的实例吗?
我刚刚开始使用Python的模拟库来帮助编写更简洁和隔离的单元测试.我的情况是我有一个类从一个非常多毛的格式读取数据,我想在这个类上测试一个以干净格式呈现数据的方法.
class holds_data(object):
def __init__(self, path):
"""Pulls complicated data from a file, given by 'path'.
Stores it in a dictionary.
"""
self.data = {}
with open(path) as f:
self.data.update(_parse(f))
def _parse(self, file):
# Some hairy parsing code here
pass
def x_coords(self):
"""The x coordinates from one part of the data
"""
return [point[0] for point in self.data['points']]
Run Code Online (Sandbox Code Playgroud)
上面的代码简化了我的工作.实际上,这_parse
是一个相当重要的方法,我在功能级别上进行了测试.
但是,我希望能够x_coords
在单元测试级别进行测试.如果我通过给它一个路径来实例化这个类,它将违反单元测试的规则,因为:
在以下情况下,测试不是单元测试:
- 它涉及文件系统
所以,我希望能够修改__init__
方法holds_data
,然后只需填写self.data
所需的部分x_coords
.就像是: …
给出x = C.f
之后:
class C:
def f(self):
pass
Run Code Online (Sandbox Code Playgroud)
我会打电话给谁x
回来C
?
我能做的最好的是exec
解析部分x.__qualname__
,这是丑陋的:
exec('d = ' + ".".join(x.__qualname__.split('.')[:-1]))
Run Code Online (Sandbox Code Playgroud)
对于一个用例,想象一下我想要一个装饰器来添加super
对它应用的任何方法的调用.那个只给出函数对象的装饰器怎么能把类带到super
(???
下面)?
def ensure_finished(iterator):
try:
next(iterator)
except StopIteration:
return
else:
raise RuntimeError
def derived_generator(method):
def new_method(self, *args, **kwargs):
x = method(self, *args, **kwargs)
y = getattr(super(???, self), method.__name__)\
(*args, **kwargs)
for a, b in zip(x, y):
assert a is None and b is None
yield
ensure_finished(x)
ensure_finished(y)
return new_method
Run Code Online (Sandbox Code Playgroud) 为了重用一些被定义为不同类的实例方法的现有代码,我想要做类似以下的事情:
class Foo(object):
def __init__(self):
self.name = "Foo"
def hello(self):
print "Hello, I am " + self.name + "."
class Bar(object):
def __init__(self):
self.name = "Bar"
bar = Bar()
Foo.hello(bar)
Run Code Online (Sandbox Code Playgroud)
但结果是:
TypeError:必须使用Foo实例作为第一个参数调用未绑定方法hello()(改为使用Bar实例)
这样的事情可能吗?
我应该清楚,我知道这是一个坏主意.显然,真正的解决方案是一些重构.我只是觉得必须有一种方法,事实证明存在.
感谢您的评论.
我有一个基类,其中有两个派生自它的类。我希望基类的方法的行为有所不同,具体取决于参数是否与派生类具有相同的类型,或者只是基类的实例但类型不同。这是当前的实现:
class MyBase:
def __init__(self, foo: int):
self.foo = foo
def __eq__(self, other):
return self.foo == other.foo
class MyDerived_1(MyBase):
def __init__(self, foo: int, bar: int):
super().__init__(foo)
self.bar = bar
class MyDerived_2(MyBase):
def __init__(self, foo: int, bar: int):
super().__init__(foo)
self.bar = bar
def __eq__(self, other):
if type(other) == type(self):
return self.bar == other.bar
elif isinstance(other, MyBase):
return super().__eq__(other)
else:
return False
Run Code Online (Sandbox Code Playgroud)
在倒数第四行中,我必须明确引用 MyBase。也许这很好,但我的理解是“super”关键字的一个要点是它应该允许您更改基类,而不必重新编写类中的任何内容。因此,该解决方案的一个潜在问题是,如果 MyBase 发生更改,那么init会很好,因为它调用“super”,但eq不会更新其行为。
所以我尝试用“type(super)”或“type(super())”替换“MyBase”,但这些不引用超类,它们引用对象“super”的类。
请注意,此问题不同于:
获取父类名? 获取Python 3等中未绑定方法对象的定义类。
因为一旦对象被初始化,他们就会寻找父类。
我想我应该能够通过运行 MRO 找到超级类。但这似乎是一个糟糕的解决方案,因为我不是在寻找整个继承树,我只是想知道超类的类型。
有没有办法从“超级”中提取这些信息?
所以我需要在一个类中有一些路由,但是路由方法需要有self
attr(访问类的属性)。但是,FastAPI 然后假定self
是它自己的必需参数并将其作为查询参数放入
这就是我所拥有的:
app = FastAPI()
class Foo:
def __init__(y: int):
self.x = y
@app.get("/somewhere")
def bar(self): return self.x
Run Code Online (Sandbox Code Playgroud)
但是,422
除非您转到 ,否则它将返回/somewhere?self=something
。问题在于,那self
是 str,因此没用。
我需要一些我仍然可以访问的方法,self
而无需将其作为必需的参数。
我想写一个装饰器,使类的方法可以被其他方看到; 然而,我所描述的问题与该细节无关.代码看起来大致如下:
def CLASS_WHERE_METHOD_IS_DEFINED( method ):
???
def foobar( method ):
print( CLASS_WHERE_METHOD_IS_DEFINED( method ) )
class X:
@foobar
def f( self, x ):
return x ** 2
Run Code Online (Sandbox Code Playgroud)
我的问题在于装饰foobar()
者看到方法的那一刻,它还无法调用; 相反,它可以看到它的未绑定版本.也许这可以通过在类上使用另一个装饰器来解决,该装饰器将处理对绑定方法必须做的任何事情.我将尝试做的下一件事是在装饰方法通过装饰器时简单地使用属性标记,然后使用类装饰器或元类来进行后处理.如果我得到这个工作,那么我不必解决这个谜语,这仍然让我困惑:
任何人都可以在上面的代码中填写有意义的行,CLASS_WHERE_METHOD_IS_DEFINED
以便装饰器可以实际打印出f
定义的类,它被定义的那一刻?或者在python 3中排除了这种可能性?
我正在编写一个 GUI 库,我想让程序员提供有关他们程序的元信息,我可以用它来微调 GUI。我打算为此目的使用函数装饰器,例如这样:
class App:
@Useraction(description='close the program', hotkey='ctrl+q')
def quit(self):
sys.exit()
Run Code Online (Sandbox Code Playgroud)
问题是这些信息需要绑定到相应的类。例如,如果该程序是图像编辑器,它可能有一个Image
提供更多用户操作的类:
class Image:
@Useraction(description='invert the colors')
def invert_colors(self):
...
Run Code Online (Sandbox Code Playgroud)
然而,由于未绑定方法的概念已在 python 3 中删除,因此似乎没有办法找到函数的定义类。(我找到了这个旧答案,但这在装饰器中不起作用。)
那么,既然装饰器看起来不起作用,那么最好的方法是什么?我想避免使用类似的代码
class App:
def quit(self):
sys.exit()
Useraction(App.quit, description='close the program', hotkey='ctrl+q')
Run Code Online (Sandbox Code Playgroud)
如果可能的话。
为了完整起见,@Useraction
装饰器看起来有点像这样:
class_metadata= defaultdict(dict)
def Useraction(**meta):
def wrap(f):
cls= get_defining_class(f)
class_metadata[cls][f]= meta
return f
return wrap
Run Code Online (Sandbox Code Playgroud) 考虑以下课程:
class Foo(object):
def bar(self):
print(self)
Run Code Online (Sandbox Code Playgroud)
在Python 2(2.7.13)中,bar()
作为类方法调用会引发异常:
>>> Foo.bar('hello')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got str instance instead)
>>> Foo.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got nothing instead)
Run Code Online (Sandbox Code Playgroud)
当bar()
作为实例方法调用时,它self
在没有参数的情况下被识别为实例
>>> Foo().bar('hello')
Traceback (most recent …
Run Code Online (Sandbox Code Playgroud) 该__qualname__
属性对我很有用,因为它使函数具有上下文关系;但是,我很难将其用于我的用例,因为:
__qualname__
返回一个字符串。对于我的用例,我需要引用父对象。
__qualname__
有时返回super
类而不是引用的类。例如:
class Parent():
def __init__(self):
pass
class Child(Parent):
pass
print(Child.__init__.__qualname__) # Prints: "Parent.__init__"
Run Code Online (Sandbox Code Playgroud)
我正在开发的包需要足够强大,据我所知,边缘情况__qualname__
没有记录。
除了使用 解析Python 文件之外ast
,还可以__qualname__
通过检查在Python3 中重新实现吗?Python是如何实现的__qualname__
?在重新实现核心功能时,我认为我将能够根据我的用例进行调整。
先前的研究:
qualname
实现:https://github.com/wbolster/qualname/blob/master/qualname.py__qualname__
获取引用:获取Python 3中未绑定方法对象的定义类__qualname__
stackoverflow:在早期 Python 中重现 Python 3.3 __qualname__ 的效果我无法在 Python 源代码中找到 qualname 实现。
python ×12
python-3.x ×5
decorator ×2
oop ×2
class ×1
coding-style ×1
fastapi ×1
inheritance ×1
mocking ×1
python-2.6 ×1
python-3.3 ×1
self ×1
super ×1
superclass ×1
unit-testing ×1