我可以更改Python绑定的方法对象吗';s\uuuu str\uuuuu()属性?
我想更改类的方法之一的我可以更改Python绑定的方法对象吗';s\uuuu str\uuuuu()属性?,python,python-3.x,instance,overriding,Python,Python 3.x,Instance,Overriding,我想更改类的方法之一的\uu str\uu()属性 (注意:不要与“尝试更改方法\uu str\uu()”混淆。) 我有一个类MyClass,它有一个方法“some_method”。我可以通过以下方式更改MyClass的显示方式: class MyClass(): def __init__(self): pass def some_method(self): pass def __str__(self): return "I'm an instance of MyClas
\uu str\uu()
属性
(注意:不要与“尝试更改方法\uu str\uu()
”混淆。)
我有一个类MyClass,它有一个方法“some_method”。我可以通过以下方式更改MyClass的显示方式:
class MyClass():
def __init__(self): pass
def some_method(self): pass
def __str__(self): return "I'm an instance of MyClass!"
当我实例化并打印MyClass时:
print(my_class)
我得到:
我是MyClass的一个实例代码>
当我
print(my_class.some_method)
我得到:
我想看到的是:
你在my_类实例中使用的某个_方法代码>
我已尝试覆盖some\u方法的str方法
:
def some_method(self):
def __str__(self):
return "You dope!"
但是没有爱
试图在IPython对其进行暴力也没有更好的结果:
my_class.some_method.__str__ = lambda: "You Dope!"
给予
AttributeError:'method'object attribute'\uuuu str\uuuuuuuu'是只读的
是否有一种简单的编程方法(最好是在Python 3中)?您需要使用自定义类而不是类函数:
class CustomFunction(object):
def __init__(self, name):
self.name = name
def __call__(func, self):
# This is the actual function
pass
def __get__(func, instance=None, type_=None):
class CustomMethod(object):
def __init__(self, instance, type_):
self.im_self = instance
self.im_class = type_
def __call__(self, *args, **kw):
return func(self.im_self, *args, **kw)
def __str__(self):
return '{} in the instance {} you Dope!'.format(func.name, self.im_self)
return CustomMethod(instance, type_)
然后在课堂上使用这个:
class MyClass():
def __init__(self): pass
some_method = CustomFunction('some_method')
演示:
>打印MyClass()。一些方法
在你使用的实例中使用了一些方法!
这是因为函数是;当调用\uuuu get\uuuu
方法时,它们返回方法。只需在方法上方添加@toStr(“这是%s您的摄影!:p”)
class MyClass():
@toStr("This is %s You Dope! :P")
def some_method(self):
print("method is doing something... Here is an attrbute... "+str(self.kk))
def __str__(self): return "I'm an instance of MyClass!"
def __init__(self):
self.some_method.real_self = self
self.kk = [":D"]
c = MyClass()
print(c)
c.some_method()
print(c.some_method)
输出:
I'm an instance of MyClass!
method is doing something... Here is an attrbute... [':D']
This is some_method You Dope! :P
Called re-repred method.
rc.re_repr_method.__name__ = re_repr_method
Test of custom repr.
在类上方的某个位置(可能是一个单独的文件)添加以下内容以创建注释:
def toStr(str):
def decorator(f):
class _temp:
def __call__(self, *args, **kwargs):
return f(self.real_self, *args, **kwargs)
def __str__(self):
return str%f.__name__
return _temp()
return decorator
请注意,在\uu init\uuuu
中需要self.some\u method.real\u self=self
,以确保将正确的self
传递给包装方法。我遇到了同样的问题,我对这里的两种解决方案都不满意。Martijn使用描述符的解决方案是正确的方法,但它没有提供装饰器的解决方案那么优雅(而且一些参数名称的选择以及他的解决方案的结构是不必要的混淆)。Navin的解决方案不是一个好方法,因为它需要手动设置“真实自我”;这正是描述符的目的。这里我想覆盖uuu repr uuuu而不是uuu str uuu,但这只是一个细节,解决方案是一样的
这是我的decorator,它返回一个描述符解决方案:
from functools import update_wrapper
# the usual outer function to allow the decorator to accept an argument
def custom_repr(repr_text):
# the decorator itself
def method_decorator(method):
# Wrap the method in our own descriptor.
class CustomReprDescriptor(object):
def __get__(self, instance, owner):
# Return our wrapped method when we call instance.method
# This class encapsulates the method
class MethodWrapper(object):
# Callable with custom __repr__ method
# Capture the instance and owner (type) from the __get__ call
def __init__(self):
self.im_self = instance
self.im_class = owner
self.im_func = method
# Call the wrapped method using the captured instance
def __call__(self, *args, **kwargs):
return self.im_func(self.im_self, *args, **kwargs)
# Capture the custom __repr__ text from the decorator call
def __repr__(self):
return repr_text
# The call to __get__ returns our wrapped method with custom __repr__
return update_wrapper(MethodWrapper(), method)
# The decorator returns our custom descriptor
return CustomReprDescriptor()
return method_decorator
class TestClass(object):
@custom_repr("Test of custom repr.")
def re_repr_method(self):
print "Called re-repred method."
tc = TestClass
tc.re_repr_method()
print "rc.re_repr_method.__name__ = " + tc.re_repr_method.__name__
print repr(tc.re_repr_method)
输出:
I'm an instance of MyClass!
method is doing something... Here is an attrbute... [':D']
This is some_method You Dope! :P
Called re-repred method.
rc.re_repr_method.__name__ = re_repr_method
Test of custom repr.
理解所有这一切的关键是,当您在python中的类声明中编写方法时,您没有做任何特殊的事情——只是在该类的命名空间中定义一个函数。然而,一些语法上的甜点开始起作用(或者至少我相信会发生这种情况):Python然后将该方法包装在一个描述符中,该描述符处理以类的实例作为自参数调用该函数。所以,我们需要做的就是自己迈出这一步;与其让Python将我们的类级函数转换成一个方法,不如将它封装在一个描述符中,该描述符的u get u u方法返回一个可调用的,其u call u u方法调用我们想要作为方法的函数,但它有一个我们选择的u repr u u方法。愚蠢的问题:Python方法甚至有属性吗?我不知道python方法是一个对象。。。是吗?@GreenAsJade:一切都是物体。但这并不意味着该语言可以轻松设置属性。@GreenAsJade正如他们所说,一切都是一个对象。是的,绑定方法是一个对象,至于这个问题,我认为你不能在绑定方法对象上设置属性。但是,您可以将函数包装在一个描述符中,该描述符构造一个自定义的绑定方法,比如对象(使用您想要的任何方法)来代替内置的绑定方法类型。如果希望print[x.some\u method,x.other\u method]
正常工作,则需要替代\u repr\uu
。在这种情况下,我建议将
保留在字符串周围。在这种情况下,“some_method”是MyClass的类变量吗?@GreenAsJade:所有常规方法也都是类属性;我刚刚制作了一个自定义的。这个实现很奇怪。我花了很长时间才理解您使用func
和self
参数所做的工作。我会发现一个基于decorator的实现更加清晰。@Martijn在我看来,这不是我第一次看到你写“函数是描述符”。但我觉得这是不对的。如果foo
是一个函数,hasattr(foo.\uuu class\uuuuuuuuu,“\uuuu get\uuuuuuuuuuu”)
是真的。但是,这并不能使foo
成为描述符,因为:1/描述符是描述符定义类的实例,2/此实例必须定义为所有者类中的属性。简而言之,描述符是可以通过点符号访问的对象。所以严格来说,任何类之外的自由函数都不是描述符。您是否看到类似的情况?不,描述符是实现。你看过那本书了吗?函数是描述符,因为函数有一个\uu get\uuu()
方法。在f(self,*args,**kwargs)
中,实际上是将\u temp
的实例传递给f
。这看起来确实不错。我喜欢decorator定义在另一个文件中。我可以把它藏在图书馆里,远离用户。有没有办法让decorator自动提取方法名,而不是手动将其传递给decorator?@JS。是的,我已经修改了它,使用方法的\uuuu name\uuuu
来生成字符串。这个实现不起作用。该方法接收到错误的self
@AshwiniChaudhary值。我已修改\u temp
以存储正确的self
,并在调用f
时使用该值。