在运行时设置点属性?

时间:2012-01-16 23:25:14

标签: python

我正在嘲笑一些数据,我需要能够通过点语法访问属性,以便保持运行时代码的顺序。当我尝试执行以下操作时,出现错误:

mockdata = object()
mockdata.name = "Hello"
object_under_test.evaluate(mockdata)

如何编写Python代码,使我能够设置这样的属性而无需创建类?

4 个答案:

答案 0 :(得分:6)

创建可以接受属性分配的 object 变体:

>>> class Object(object):
         pass
>>> mockdata = Object()
>>> mockdata.someattr = somevalue

答案 1 :(得分:2)

如果您不想“创建一个类”(我将使用class关键字来定义一个类),您可以这样做:

mockdata = type("Mockdata", (object,), {})()

这仍然会创建一个类(object的子类),但它在实例化之前没有为它指定一个名称,我想你可能会觉得它更适合这种一次性使用,因为它没有不要弄乱你的名字空间。

答案 2 :(得分:1)

是的,正如Raymond Hettinger所说,只需创建类可以保存属性,但是大多数情况下,当您进行模拟时,您可能需要设置一些返回值来验证某些方法,并且您可以像通常那样执行此操作任何课程。如果你想在某个可用类中模拟一个方法,那么有些库可以帮助你做到这一点,其中一个被称为Mock

答案 3 :(得分:1)

其他想法,按顺序递减(IMO)。

  1. 使用proper mocking library

    我建议这样做的原因是你通常想要模拟这样的对象用于测试目的。如果是这样,您希望确保.evaluatemockdata做正确的事情:调用正确的方法,访问正确的属性等等。模拟库允许您在测试框架内模拟对象,所以你不必手动检查所有这些。

  2. 使用dict - 将字符串映射到值的常用方法:

    mockdata = {}
    mockdata["name"] = "Hello"
    object_under_test.evaluate(mockdata)
    
  3. 如果您知道自己想要的字段,请使用NamedTuple

    import collections
    MockData = collections.namedtuple('MockData', ('name', 'value', ...))
    mockdata = MockData(name="Hello", value=None, ...)
    object_under_test.evaluate(mockdata)
    
  4. 使用任何旧对象。 lambda: None class Object(object): pass将会有效。

  5. 如果你是邪恶的,请使用attrdict。 (注意:实际上并没有这样做。但你可能会发现它很酷。)

    class attrdict(dict):
        def __init__(self, *args, **kwargs):
            dict.__init__(self, *args, **kwargs)
            self.__dict__ = self
    
    mockdata = attrdict()
    mockdata["name"] = "Hello"
    object_under_test.evaluate(mockdata)
    

  6. 顺便说一句,你可能想知道为什么object().name = "Hello"不起作用。这是因为object()是一个奇怪的野兽,你可能不想使用它。正如docs所说:

      

    注意object没有__dict__,因此您无法将任意属性分配给object类的实例。