- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含成员对象的类。我想像调用容器类的方法一样调用成员的方法。
以下示例说明了(但在不同的上下文中)我想要做的事情。
假设我们有两个类代表两种不同类型的产品:玩具和鞋子。每个类都有两个方法,比如说 weight()
和description()
,它明显返回元素的重量和元素的描述。
现在我想将这些产品放入单独的盒子中 - 每个盒子将包含一个 Toy
要么是单个 Shoe
.
我希望仍然能够访问方法 weight()
和description()
,但是我希望他们成为 Box
的成员实例。另外,我不想专门实现方法 weight()
和description()
在 Box
类,因为我不想在 Box
中实现更多方法每当向玩具和鞋子添加新方法时,都会调用类。
这是一个让我高兴的“最终结果”的例子:
# Define our products
product1 = Toy('plastic gun', 200)
product2 = Shoe('black leather shoes', 500)
# Now place them in boxes
box1 = Box(product1, box_code='A1234')
box2 = Box(product2, box_code='V4321')
# I want to know the contents of the boxes
box1.description()
box2.description()
# Desired results
>> plastic gun
>> black leather shoes
我的实现思路是这样的。
class Product():
def __init__(self, description, weight):
self.desc = description
self.wght = weight
def description(self):
return self.desc
def weight(self):
return self.weight
class Toy(Product):
pass
class Shoe(Product):
pass
class Box(object):
def __init__(self, product, box_code):
self.box_code = box_code
self.product = product
def __getattribute__(self, name):
# Any method that is accessed in the Box instance should be replaced by
# the correspondent method in self.product
return self.product.__getattribute__(name)
但是这不起作用!如果我运行第一个代码块中显示的“所需”示例,我会得到无限递归。那么,如何优雅地做到这一点呢?
请注意 Box
有自己的参数box_code
,将来我可能想向 Toy
添加新方法和Shoes
(例如,促销代码或其他),而无需修改类 Box
.
好的,伙计们,我热切地等待着你们的回复。
更新:问题的答案感谢 Interjay 和 Mike Boer 的帮助。
我只需替换方法的定义 __getattribute__
在类里面Box
通过__getattr__
正如 Interjay 所建议的那样,它运行得非常完美。 Box 类的正确定义是:
class Box(object):
def __init__(self, product, box_code):
self.box_code = box_code
self.product = product
def __getattr__(self, name):
# Any method that is accessed in the Box instance should be replaced by
# the correspondent method in self.product
return self.product.__getattribute__(name)
更新:使用 __setattr__
完成示例
在使用 getattr 方法纠正问题后,我注意到当我想要设置属性时,我的类没有达到所需的行为。例如,如果我尝试:
box1.desc = 'plastic sword'
没有更改product1的描述(封装在box1中),而是在box1中创建了一个名为“desc”的新成员。为了解决这个问题,我必须定义 __setattr__
函数,如下图:
def __setattr__(self, name, value):
setattr(self.product, name, value)
但是,仅添加此函数就会创建递归调用,因为在 __init__
中我尝试分配 self.product = product
' 调用函数 __setattr__
,它没有找到成员 self.product
,因此调用函数 __setattr__
再次,无限递归。
为了避免这个问题,我必须更改__init__
方法以便使用类的字典分配新成员。类的完整定义Box
那么就是:
class Box(object):
def __init__(self, product, box_code):
self.__dict__['product'] = product
self.box_code = box_code
def __getattr__(self, name):
# Any method that is accessed in the Box instance should be replaced by
# the correspondent method in self.product
return getattr(self.product, name)
def __setattr__(self, name, value):
setattr(self.product, name, value)
现在一件有趣的事情...如果我首先定义成员 self.product
,如上图,程序运行正常。但是,如果我尝试首先定义成员 self.box_code
,程序再次遇到递归循环问题。有谁知道为什么吗?
最佳答案
您可以按照建议使用 __getattr__
而不是 __getattribute__
。对于不存在的属性的任何属性访问都会调用该方法。
如果您确实想覆盖(几乎)所有属性访问,则继续使用 __getattribute__
并如此定义它:
def __getattribute__(self, name):
return getattr(object.__getattribute__(self, 'product'), name)
关于Python:使用 __getattribute__ 按名称调用实例成员的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1810526/
给定: In [37]: class A: ....: f = 1 ....: In [38]: class B(A): ....: pass ....: In
class Shadow(object): pass class Test(object): a = 1 b = 2 _shadow = Shadow() de
我想在调用特定方法之前调用带有参数的函数的包装方法。所以我想我必须重写 __getattribute__ 方法。 以下是代码示例: def wrapper(func): return func
class test(): name = 'arthur' def __getattribute__(self, value): return super().__getattribu
根据 python 描述符指南 https://docs.python.org/howto/descriptor.html 新样式类中的方法对象是使用描述符实现的,以避免在属性查找中对它们进行特殊封装
这个对我来说似乎有点棘手。前段时间我已经设法用类似的东西覆盖实例的方法: def my_method(self, attr): pass instancemethod = type(self.
考虑以下几点: class A(object): def __init__(self): print 'Hello!' def foo(self): p
我想覆盖对类中一个变量的访问,但正常返回所有其他变量。如何使用 __getattribute__ 完成此操作? 我尝试了以下操作(这也应该说明我正在尝试做的事情)但我得到一个递归错误: class D
我尝试重写数据类中的__getattribute__特殊方法,以获得属性的格式化版本。 @dataclass class _BaseRouteRegistry: VERSION = '1'
我尝试重写数据类中的__getattribute__特殊方法,以获得属性的格式化版本。 @dataclass class _BaseRouteRegistry: VERSION = '1'
我有以下代码: #-*-coding:utf-8-*- class A(object): def __init__(self, x): self.x = x def _
为了更好地理解这个问题,这里有一个例子: class Parent: def __getattribute__(self, attr): print('ha!')
我有一个包含成员对象的类。我想像调用容器类的方法一样调用成员的方法。 以下示例说明了(但在不同的上下文中)我想要做的事情。 假设我们有两个类代表两种不同类型的产品:玩具和鞋子。每个类都有两个方法,比如
我阅读了一些关于 python 的对象属性查找的内容(此处:https://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/#o
class B(object): """new style class""" def __getattribute__(self, name): print '__getatt
这是从 Python 2.7.12 文档(3.4.12. 新型类的特殊方法查找¶)中检索到的代码片段: In addition to bypassing any instance attributes
如果这个问题有重复,抱歉,我没有找到它,如果有人找到,我会删除这个问题。 我有这个简单的 python 类: class NothingSpecial: @classmethod
我有以下类(class): class StrLogger(str): def __init__(self, *args): self._log_ = [] s
似乎 __getattribute__ 只有两个参数 (self, name)。 然而,在实际代码中,我拦截的方法实际上是带参数的。 无论如何都可以访问这些参数吗? 谢谢, 查理 最佳答案 __get
Python in a Nutshell 描述: 从类中获取属性时的查找过程,例如cls.name(参见 Why are the lookup procedures for getting an at
我是一名优秀的程序员,十分优秀!