如何创建一个对象并为其添加属性?

2025-03-18 08:55:00
admin
原创
46
摘要:问题描述:我想在 Python 中创建一个动态对象,然后为其添加属性。这不起作用:obj = object() obj.somefield = "somevalue" AttributeError:'object' 对象没有属性 'somefield'有关其不起作用的原因的详细信息,请参阅...

问题描述:

我想在 Python 中创建一个动态对象,然后为其添加属性。这不起作用:

obj = object()
obj.somefield = "somevalue"

AttributeError:'object' 对象没有属性 'somefield'


有关其不起作用的原因的详细信息,请参阅无法在“对象”类的实例上设置属性。


解决方案 1:

内置函数object可以实例化,但不能设置任何属性。(我希望它可以,就为了这个目的。)这是因为它没有一个可以__dict__保存属性的函数。


我通常只是这样做:

class Object(object):
    pass

obj = Object()
obj.somefield = "somevalue"

但是请考虑Object根据该类所保存的数据赋予其一个更有意义的名称。


另一种可能性是使用允许属性访问的子类dict来获取键:

class AttrDict(dict):
    def __getattr__(self, key):
        return self[key]

    def __setattr__(self, key, value):
        self[key] = value

obj = AttrDict()
obj.somefield = "somevalue"

使用字典实例化对象属性:

d = {"a": 1, "b": 2, "c": 3}

for k, v in d.items():
    setattr(obj, k, v)

解决方案 2:

你可以使用我古老的Bunch配方,但如果你不想创建“bunch 类”,Python 中已经有一个非常简单的类——所有函数都可以具有任意属性(包括 lambda 函数)。因此,以下方法有效:

obj = lambda: None
obj.somefield = 'somevalue'

与古老的菜谱相比,清晰度的降低是否Bunch可以接受,这是一个风格决定,我当然会把它留给你来决定。

解决方案 3:

types.SimpleNamespacePython 3.3+ 中有一个类:

obj = someobject
obj.a = SimpleNamespace()
for p in params:
    setattr(obj.a, p, value)
# obj.a.attr1

collections.namedtupletyping.NamedTuple可用于不可变对象。PEP 557——数据类 提出了一种可变的替代方案。

为了获得更丰富的功能,您可以尝试attrs包。查看示例用法。pydantic也许也值得一看。

解决方案 4:

您也可以直接使用类对象;它会创建一个命名空间:

class a: pass
a.somefield1 = 'somevalue1'
setattr(a, 'somefield2', 'somevalue2')

解决方案 5:

mock模块基本上就是为此制作的。

import mock
obj = mock.Mock()
obj.a = 5

解决方案 6:

有几种方法可以实现此目标。基本上,您需要一个可扩展的对象。

obj = type('Test', (object,), {})  
obj.b = 'fun'
obj = lambda:None
obj.b = 'fun'
class Test:
  pass

obj = Test()
obj.b = 'fun'

解决方案 7:

现在您可以这样做(不确定这是否与 evilpie 的答案相同):

MyObject = type('MyObject', (object,), {})
obj = MyObject()
obj.value = 42

解决方案 8:

尝试下面的代码:

$ python
>>> class Container(object):
...     pass 
...
>>> x = Container()
>>> x.a = 10
>>> x.b = 20
>>> x.banana = 100
>>> x.a, x.b, x.banana
(10, 20, 100)
>>> dir(x)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__',     '__sizeof__', 
'__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'banana']

解决方案 9:

正如文档所述:

注意object没有,所以不能将任意属性分配给类的实例__dict__`object`

您可以只使用虚拟类实例。

解决方案 10:

这些解决方案在测试过程中非常有用。基于其他人的答案,我在 Python 2.7.9 中执行了此操作(没有 staticmethod 时,我得到了 TypeError(未绑定方法...):

In [11]: auth = type('', (), {})
In [12]: auth.func = staticmethod(lambda i: i * 2)
In [13]: auth.func(2)
Out[13]: 4

解决方案 11:

如果我们可以在创建嵌套对象之前确定并聚合所有属性和值,那么我们就可以创建一个在创建时采用字典参数的新类。

# python 2.7

class NestedObject():
    def __init__(self, initial_attrs):
        for key in initial_attrs:
            setattr(self, key, initial_attrs[key])

obj = someobject
attributes = { 'attr1': 'val1', 'attr2': 'val2', 'attr3': 'val3' }
obj.a = NestedObject(attributes)
>>> obj.a.attr1
'val1'
>>> obj.a.attr2
'val2'
>>> obj.a.attr3
'val3'

我们还可以允许关键字参数。请参阅此文章。

class NestedObject(object):
    def __init__(self, *initial_attrs, **kwargs):
        for dictionary in initial_attrs:
            for key in dictionary:
                setattr(self, key, dictionary[key])
        for key in kwargs:
            setattr(self, key, kwargs[key])


obj.a = NestedObject(attr1='val1', attr2='val2', attr3= 'val3')

解决方案 12:

要从字典创建对象:

class Struct(object):
    def __init__(self, d):
        for key in d.keys():
            self.__setattr__(key, d[key])

用法:

>>> obj = Struct({'a': 1, 'b': 2})
>>> obj.a
1

解决方案 13:

您正在使用哪些对象?刚刚用示例类尝试了一下,效果很好:

class MyClass:
  i = 123456
  def f(self):
    return "hello world"

b = MyClass()
b.c = MyClass()
setattr(b.c, 'test', 123)
b.c.test

我得到了123答案。

我发现唯一失败的情况是当您尝试setattr一个内置对象时。

更新:从评论来看,这是重复的:为什么不能在 python 中向对象添加属性?

解决方案 14:

我认为最简单的方法是通过收藏模块。

import collections
FinanceCtaCteM = collections.namedtuple('FinanceCtaCte', 'forma_pago doc_pago get_total')
def get_total(): return 98989898
financtacteobj = FinanceCtaCteM(forma_pago='CONTADO', doc_pago='EFECTIVO',
                                get_total=get_total)

print financtacteobj.get_total()
print financtacteobj.forma_pago
print financtacteobj.doc_pago

解决方案 15:

如果你正在寻找链式分配,来执行诸如 django 模型模板抽象属性分配之类的操作:

from types import SimpleNamespace


def assign(target, *args, suffix):
    ls = target
    for i in range(len(args) - 1):
        a = args[i]
        ns = SimpleNamespace()
        setattr(ls, a, ns)
        ls = ns
    setattr(ls, args[-1], suffix)
    return ls


a = SimpleNamespace()
assign(a, 'a', 'b', 'c', suffix={'name': 'james'})
print(a.a.b.c)
# {'name': 'james'}

它允许您将模型作为传递target,并为其分配结束属性。

解决方案 16:

你可以使用Alex Martelli 的经典Bunch类。我最喜欢的类是

class Bunch(dict):
    def __init__(self, **kwds):
        self.update(kwds)
        self.__dict__ = self

与此处的其他答案相比,此解决方案允许您以表达式形式构建这样的内联类:

map_data = Bunch(
        directions=[d for d in parsed_data.directions],
        connections={c.start: Bunch(L=c.left, R=c.right) for c in parsed_data.connections})
print(map_data)

而且,因为Bunch ,所以dict这会打印出一些好的东西!

{'directions': ['R', 'L'], 'connections': {'AAA': {'L': 'BBB', 'R': 'CCC'}, 'BBB': {'L': 'DDD', 'R': 'EEE'}, 'CCC': {'L': 'ZZZ', 'R': 'GGG'}, 'DDD': {'L': 'DDD', 'R': 'DDD'}, 'EEE': {'L': 'EEE', 'R': 'EEE'}, 'GGG': {'L': 'GGG', 'R': 'GGG'}, 'ZZZ': {'L': 'ZZZ', 'R': 'ZZZ'}}}

相比之下,自定义Object类(例如当前的最佳答案)打印的内容不太好看:

<__main__.Object object at 0x7025cae62b90>

事实上,你可以将其用作Bunch表达式,同时也允许你将其用作列表或字典理解的一部分,如上所述:

connections={c.start: Bunch(L=c.left, R=c.right) for c in parsed_data.connections})`

使用这里发布的任何其他解决方案来实现这一点都非常困难。

您也可以直接从字典构造这样的对象:

my_dict = {'directions': 'LRLRLL', 'connections': []}
map_data = Bunch(**my_dict)
print(map_data)

与其他已发布的解决方案相比,此解决方案的另一大优势是,您的对象既是字典,又是对象。这意味着:

  1. 如果您现有的代码使用字典语法(map_data['directions']),您可以迁移到Bunch,并逐步更新现有代码。

  2. 调试太棒了!你可以打印、漂亮打印、遍历键/值,以及你想用字典做的一切!

解决方案 17:

虽然已经很晚了,但这是我对一个对象的看法,这个对象恰好保存了应用程序中的一些有用路径,但你可以将它调整为任何你想要的信息,你可以使用 getattr 和点符号来访问它(我认为这才是这个问题的真正意义所在):

import os

def x_path(path_name):
    return getattr(x_path, path_name)

x_path.root = '/home/x'
for name in ['repository', 'caches', 'projects']:
    setattr(x_path, name, os.path.join(x_path.root, name))

这很酷,因为现在:

In [1]: x_path.projects
Out[1]: '/home/x/projects'

In [2]: x_path('caches')
Out[2]: '/home/x/caches'

因此,这使用像上述答案一样的函数对象,但使用函数来获取值(如果您愿意,您仍然可以使用(getattr, x_path, 'repository')而不是)。x_path('repository')

解决方案 18:

di = {}
for x in range(20):
    name = '_id%s' % x
    di[name] = type(name, (object), {})
    setattr(di[name], "attr", "value")

解决方案 19:

我看到的另一种方式是这样的:

import maya.cmds

def getData(objets=None, attrs=None):
    di = {}
    for obj in objets:
        name = str(obj)
        di[name]=[]
        for at in attrs:
            di[name].append(cmds.getAttr(name+'.'+at)[0])
    return di

acns=cmds.ls('L_vest_*_',type='aimConstraint')
attrs=['offset','aimVector','upVector','worldUpVector']

getData(acns,attrs)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用