首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类名称类

类名称类
EN

Stack Overflow用户
提问于 2011-02-27 02:29:30
回答 5查看 6.7K关注 0票数 10

当我需要一个快速的单用类时,我发现自己经常在python代码中编写这个类。

代码语言:javascript
复制
class Struct(object):
   def __init__( self, **kwargs ):
      for k in kwargs:
         setattr(self,k,kwargs[k])

基本的想法是,这样我就可以快速地做这样的事情:

代码语言:javascript
复制
foo = Struct( bar='one', baz=1 )
print foo.bar
foo.baz += 1
foo.novo = 42 # I don't do this as often.

当然,这不是很好的扩展,添加方法是疯狂的,但即便如此,我仍然有足够的数据丢弃类,我一直在使用它。

这就是我以为名称会成为的样子。但是namedtuple的语法又大又笨重。

在标准库中是否有我还没有找到的东西,它也可以或者更好呢?

这是糟糕的风格吗?还是它有什么隐藏的缺陷?

更新

两个具体的例子,说明为什么我不只是使用一个丁字。这两个例子都可以用一个dict来完成,但它显然不是惯用的。

代码语言:javascript
复制
#I know an order preserving dict would be better but they don't exist in 2.6.
closure = Struct(count=0)
def mk_Foo( name, path ):
   closure.count += 1
   return (name, Foo( name, path, closure.count ))

d = dict([
   mk_Foo( 'a', 'abc' ),
   mk_Foo( 'b', 'def' ),
   # 20 or so more
   ] )


@contextmanager
def deleter( path ):
   control = Struct(delete=True,path=path)
   try:      
      yield control
   finally:
      if control.delete:
         shutil.rmtree(path)

with deleter( tempfile.mkdtemp() ) as tmp:
   # do stuff with tmp.path
  
   # most contexts don't modify the delete member
   # but occasionally it's needed
   if keep_tmp_dir:
      tmp.delete = False
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-02-27 02:51:06

有一个python食谱(它只是更新实例的dict而不是调用setattr) 配方52308

代码语言:javascript
复制
class Bunch(object):
    def __init__(self, **kwds):
        self.__dict__.update(kwds)
票数 9
EN

Stack Overflow用户

发布于 2016-02-14 07:29:48

在Python3.3和以后的版本中,您可以使用types.SimpleNamespace

代码语言:javascript
复制
>>> import types
>>> foo = types.SimpleNamespace(bar='one', baz=1)
>>> print(foo.bar)
one
>>> foo.baz += 1
>>> foo.novo = 42

内置类型大致相当于以下代码:

代码语言:javascript
复制
class SimpleNamespace:

    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

    def __repr__(self):
        keys = sorted(self.__dict__)
        items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
        return "{}({})".format(type(self).__name__, ", ".join(items))

    def __eq__(self, other):
        return self.__dict__ == other.__dict__

更新

从Python 3.7开始,您可以使用dataclass模块:

代码语言:javascript
复制
from dataclasses import dataclass, field

@dataclass
class Struct:
    bar: str = field(default='one')
    baz: int = field(default=1)

您可以如下所示:

代码语言:javascript
复制
foo = Struct( bar='one', baz=1 )
print(foo.bar)
foo.baz += 1
foo.novo = 42

默认情况下,它包含了等式测试和漂亮的repr:

代码语言:javascript
复制
>>> foo == Struct(bar='one', baz=2)
True
>>> foo
Struct(bar='one', baz=2)
票数 9
EN

Stack Overflow用户

发布于 2011-07-27 00:31:00

代码语言:javascript
复制
class t(dict):

   def __init__(self, **kwargs):
      for key, value in kwargs.items():
         dict.__setitem__(self, key, value)
   def __getattr__(self, key):
      return dict.__getitem__(self, key)
   def __setattr__(self, key, value):
      raise StandardError("Cannot set attributes of tuple")      
   def __setitem__(self, key, value):
      raise StandardError("Cannot set attributes of tuple")      
   def __delitem__(self, key):
      raise StandardError("Cannot delete attributes of tuple")

point = t(x=10, y=500, z=-50)
print point.x        # 10
print point.y        # 500
print point['z']     # -50
print point          # {'z': -50, 'y': 500, 'x': 10}
point.x = 100        # StandardError: cannot set attributes of tuple
point.y += 5         # StandardError: cannot set attributes of tuple
point.z = -1         # StandardError: cannot set attributes of tuple

def hypo(x, y, z):
   return (x**2 + y**2 + z**2)**0.5

print hypo(point)    # TypeError: unsupported operand type(s)
print hypo(**point)  # 502.593274925   

for k in point.items():
   print k           # ('y', 500)
                     # ('x', 10)
                     # ('z', -50)

for k in point.keys():
   print k           # x
                     # y
                     # z

for k in point.values():
   print k           # 500
                     # 10
                     # -50

print len(point)     # 3

print dict(point)    # {'y': 500, 'x': 10, 'z': -50}

这是我解决这个问题的办法。漂亮的语法,不变的(至少不诉诸一些讨厌的object.setattr()体操),轻量级和漂亮的打印。虽然你对这件事无能为力,

代码语言:javascript
复制
point = t(x=10, y=20, z=30)
d = point.x ** 2 + point.y ** 2 + point.z ** 2

有一个很好的对称

代码语言:javascript
复制
point = (10, 20, 30)
d = point[0] ** 2 + point[1] ** 2 + point[2] ** 2

而且总体上比

代码语言:javascript
复制
point = {'x': 10, 'y': 20, 'z': 30}
d = point['x'] ** 2 + point['y'] ** 2 + point['z'] ** 2
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5131044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档