我正在尝试修补类实例,但是我不太清楚如何修补类方法没问题.
>>> class Simple(object):
... def make(self, arg):
... return arg * 2
...
>>> s = Simple()
>>> def times_four(self, arg):
... return arg * 4
...
>>> Simple.make = times_four
>>> s.make(10)
40
Run Code Online (Sandbox Code Playgroud)
但是说我只想make在实例中替换,最简单的方法是什么?
>>> def times_eight(self, arg):
... return arg * 8
>>> s.make = ???
Run Code Online (Sandbox Code Playgroud) >>> class A:
... def foo(self):
... print(self)
...
>>>
>>> a = A()
>>> a.foo()
<__main__.A instance at 0x7f4399136cb0>
>>> def foo(self):
... print(self)
...
>>> a.foo = foo
>>> a.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 argument (0 given)
Run Code Online (Sandbox Code Playgroud)
我正在尝试理解 Python 中的猴子补丁。请说明错误的原因以及如何修复它。
我有Python背景(虽然完全是自学成才,所以我可能有一些不良习惯或误解),而我正在努力学习Ruby以扩大我的范围.
我正在阅读一些比较,并看到许多断言"Python不能进行元编程"(或者,更少的是,"Python不能像Meta一样简单地进行元编程").所以我离开后迅速阅读了关于元编程的内容,并且给人的印象是,它基本上是在运行时编辑类/对象的方法/行为(如果我不正确,请纠正我!).
我的印象是,由于Python是动态的,这应该不是问题.但是,我运行了以下测试代码,它没有给出我预期的响应:
>>> class foo:
... def make_hello_method(self):
... def hello(obj):
... print 'hello'
... self.hello = hello
...
>>> f = foo()
>>> f.hello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: foo instance has no attribute 'hello'
>>> f.make_hello_method()
>>> f.hello()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: hello() takes exactly 1 argument (0 given)
Run Code Online (Sandbox Code Playgroud)
我的印象是,对象的每个方法都自动将对象本身作为第一个参数传递(因此将对象方法定义为常量要求(self, [...])).怎么f没有被传递给hello()?
我了解了如何通过浏览这些链接在Python中运行时替换方法.[ Link1,Link2和Link3 ].
当我替换A类的"update_private_variable"方法时,它被替换但不更新私有变量.
import types
class A:
def __init__(self):
self.__private_variable = None
self.public_variable = None
def update_private_variable(self):
self.__private_variable = "Updated in A"
def update_public_variable(self):
self.public_variable = "Updated in A"
def get_private_variable(self):
return self.__private_variable
class B:
def __init__(self):
self.__private_variable = None
self.public_variable = None
def update_private_variable(self):
self.__private_variable = "Updated in B"
def update_public_variable(self):
self.public_variable = "Updated in B"
Run Code Online (Sandbox Code Playgroud)
在没有替换的情况下调用方法:
a_instance = A()
a_instance.update_private_variable()
print(a_instance.get_private_variable())
#prints "Updated in A"
Run Code Online (Sandbox Code Playgroud)
更换后调用方法时:
a_instance = A()
a_instance.update_private_variable = types.MethodType(B.update_private_variable, a_instance) …Run Code Online (Sandbox Code Playgroud) 我的问题涉及在类构造函数之外的方法中初始化的实例变量.这适用于Python.
我先说出我的理解:
(2)和(3)的一个例子 - 参见下面的Cat类中的self.meow和self.roar:
class Cat():
def __init__(self):
self.meow = "Meow!"
def meow_bigger(self):
self.roar = "Roar!"
Run Code Online (Sandbox Code Playgroud)我的问题:
为什么在构造函数中初始化实例变量是最佳实践?
如果实例变量在构造函数以外的方法中定期初始化,可能会出现一般/特定的混乱?(例如,在他的编程Python中读过Mark Lutz的Tkinter指南,我认为这很好,我注意到用于保存PhotoImage对象/引用的实例变量在其他方法中初始化,而不是在构造函数中初始化.它似乎没有工作问题,但从长远来看,这种做法是否会引起问题?)
在哪些情况下,在其他方法中而不是在构造函数中初始化实例变量会更好?
据我所知,实例变量不是在创建类对象时存在,而是在实例化类对象之后存在.继续我上面的代码,我证明了这一点:
>> c = Cat()
>> c.meow
'Meow!'
>> c.roar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Cat' object has no attribute 'roar'
>>> c.meow_bigger()
>>> c.roar
'Roar!'
Run Code Online (Sandbox Code Playgroud)
原样:
我想创建一个具有某些属性的对象。我想动态添加它们。与向现有对象实例添加方法类似,但使用属性而不是方法。下面是一个简单的例子。
我喜欢动态创建:
class A():
@property
def a(self):
return self._a
@a.setter
def a(self, x):
self._a = 10*x
@property
def b(self):
return self._b
@b.setter
def b(self, x):
self._b = 10*x
Run Code Online (Sandbox Code Playgroud)
要使用方法来做到这一点,我会这样做:
class B():
def __init__(self):
for i in range(70,80):
self.__dict__[chr(i)] = types.MethodType(lambda self,x: x*i, self)
Run Code Online (Sandbox Code Playgroud)
对于我尝试过的属性:
class B():
def __init__(self):
for i in range(70,80):
def tmp(self, x):
self._x = i*x
self.__dict__[chr(i)] = property(fget=lambda self: self._i, fset=tmp)
Run Code Online (Sandbox Code Playgroud)
我也找到了types.DynamicClassAttribute,但我不确定这是否有帮助。
这里提出了一个相关问题,关于向类添加属性(在 python 2 中): Dynamically add @property in python。我不知道如何将其扩展到类的实例。
我需要在swig模板类中添加一个新方法,例如:
我在myswig.i中声明了一个模板类,如下所示:
%template(DoubleVector) vector<double>;
Run Code Online (Sandbox Code Playgroud)
这将在生成的.py文件中生成一个名为"DoubleVector"的类,其中包含一些生成的方法.假设它们是func1(),func2()和func3().这些是生成的函数,我无法控制它们.现在,如果我想向这个类(DoubleVector)添加一个名为"func4()"的新方法,我该怎么办呢?可能吗?
我知道一个名为%pythoncode的标识符,但我不能用它来定义这个模板类中的新函数.
我发现为一个简单的失败的单元测试获取如此多的细节有点令人恼火。除了实际定义的断言消息之外,是否可以抑制所有内容?
Creating test database for alias 'default'...
.F
======================================================================
FAIL: test_get_sales_item_for_company (my_app.tests.SalesItemModelTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/kave/projects/my/my_app/tests.py", line 61, in test_get_sales_item_for_company
self.assertEqual(sales_items.count(), 1, 'Expected one sales item for this company, but got %s' % sales_items.count())
AssertionError: Expected one sales item for this company, but got 2
----------------------------------------------------------------------
Ran 2 tests in 0.313s
FAILED (failures=1)
Destroying test database for alias 'default'...
Run Code Online (Sandbox Code Playgroud)
我觉得这有点不必要。我需要知道失败的测试名称(方法)和断言消息。真的不需要回溯..
Traceback (most recent call last):
File "/home/kave/projects/my/my_app/tests.py", line 61, in test_get_sales_item_for_company
self.assertEqual(sales_items.count(), 1, 'Expected one sales …Run Code Online (Sandbox Code Playgroud) 首先,有A两个类变量和两个实例变量的类:
In [1]: def fun(x, y): return x + y
In [2]: class A:
...: cvar = 1
...: cfun = fun
...: def __init__(self):
...: self.ivar = 100
...: self.ifun = fun
Run Code Online (Sandbox Code Playgroud)
我们可以看到int类的类变量和实例变量都可以正常工作:
In [3]: a = A()
In [4]: a.ivar, a.cvar
Out[4]: (100, 1)
Run Code Online (Sandbox Code Playgroud)
但是,如果检查函数类型变量,情况就会改变:
In [5]: a.ifun, a.cfun
Out[5]:
(<function __main__.fun>,
<bound method A.fun of <__main__.A instance at 0x25f90e0>>)
In [6]: a.ifun(1,2)
Out[6]: 3
In [7]: a.cfun(1,2)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/future/<ipython-input-7-39aa8db2389e> …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个可以轻松扩展的模拟类。为此,我想使用类似于属性的东西,但这也提供了update一种可以针对不同用例以不同方式实现的方法:
class Quantity(object):
def __init__(self, initval=None):
self.value = initval
def __get__(self, instance, owner):
return self.value
def __set__(self, instance, value):
self.value = value
def update(self, parent):
"""here the quantity should be updated using also values from
MySimulation, e.g. adding `MySimulation.increment`, but I don't
know how to link to the parent simulation."""
class MySimulation(object):
"this default simulation has only density"
density = Quantity()
increment = 1
def __init__(self, value):
self.density = value
def update(self):
"""this one does not work because …Run Code Online (Sandbox Code Playgroud) python ×9
class ×2
constructor ×1
django ×1
instance ×1
oop ×1
python-3.x ×1
swig ×1
templates ×1
unit-testing ×1
variables ×1