对象字面量是 Pythonic 的吗?

发布于 2024-09-11 14:11:46 字数 781 浏览 6 评论 0原文

JavaScript 有对象文字,例如

var p = {
  name: "John Smith",
  age:  23
}

,.NET 有匿名类型,例如,

var p = new { Name = "John Smith", Age = 23}; // C#

可以通过(ab)使用命名参数在 Python 中模拟类似的东西:

class literal(object):
    def __init__(self, **kwargs):
        for (k,v) in kwargs.iteritems():
            self.__setattr__(k, v)
    def __repr__(self):
        return 'literal(%s)' % ', '.join('%s = %r' % i for i in sorted(self.__dict__.iteritems()))
    def __str__(self):
        return repr(self)

用法:

p = literal(name = "John Smith", age = 23)
print p       # prints: literal(age = 23, name = 'John Smith')
print p.name  # prints: John Smith

但是这种代码被认为是 Pythonic 吗?

JavaScript has object literals, e.g.

var p = {
  name: "John Smith",
  age:  23
}

and .NET has anonymous types, e.g.

var p = new { Name = "John Smith", Age = 23}; // C#

Something similar can be emulated in Python by (ab)using named arguments:

class literal(object):
    def __init__(self, **kwargs):
        for (k,v) in kwargs.iteritems():
            self.__setattr__(k, v)
    def __repr__(self):
        return 'literal(%s)' % ', '.join('%s = %r' % i for i in sorted(self.__dict__.iteritems()))
    def __str__(self):
        return repr(self)

Usage:

p = literal(name = "John Smith", age = 23)
print p       # prints: literal(age = 23, name = 'John Smith')
print p.name  # prints: John Smith

But is this kind of code considered to be Pythonic?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

雨后彩虹 2024-09-18 14:11:46

为什么不直接使用字典呢?

p = {'name': 'John Smith', 'age': 23}

print p
print p['name']
print p['age']

Why not just use a dictionary?

p = {'name': 'John Smith', 'age': 23}

print p
print p['name']
print p['age']
瞄了个咪的 2024-09-18 14:11:46

您是否考虑过使用 命名元组

使用你的字典表示法

>>> from collections import namedtuple
>>> L = namedtuple('literal', 'name age')(**{'name': 'John Smith', 'age': 23})

或关键字参数

>>> L = namedtuple('literal', 'name age')(name='John Smith', age=23)
>>> L
literal(name='John Smith', age=23)
>>> L.name
'John Smith'
>>> L.age
23

可以很容易地将这种行为包装到一个函数中,

def literal(**kw):
    return namedtuple('literal', kw)(**kw)

就像 lambda 等价物一样,

literal = lambda **kw: namedtuple('literal', kw)(**kw)

但我个人认为给“匿名”函数命名是愚蠢的

Have you considered using a named tuple?

Using your dict notation

>>> from collections import namedtuple
>>> L = namedtuple('literal', 'name age')(**{'name': 'John Smith', 'age': 23})

or keyword arguments

>>> L = namedtuple('literal', 'name age')(name='John Smith', age=23)
>>> L
literal(name='John Smith', age=23)
>>> L.name
'John Smith'
>>> L.age
23

It is possible to wrap this behaviour into a function easily enough

def literal(**kw):
    return namedtuple('literal', kw)(**kw)

the lambda equivalent would be

literal = lambda **kw: namedtuple('literal', kw)(**kw)

but personally I think it's silly giving names to "anonymous" functions

痴梦一场 2024-09-18 14:11:46

来自 ActiveState:

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

# that's it!  Now, you can create a Bunch
# whenever you want to group a few variables:

point = Bunch(datum=y, squared=y*y, coord=x)

# and of course you can read/write the named
# attributes you just created, add others, del
# some of them, etc, etc:
if point.squared > threshold:
    point.isok = 1

From ActiveState:

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

# that's it!  Now, you can create a Bunch
# whenever you want to group a few variables:

point = Bunch(datum=y, squared=y*y, coord=x)

# and of course you can read/write the named
# attributes you just created, add others, del
# some of them, etc, etc:
if point.squared > threshold:
    point.isok = 1
北陌 2024-09-18 14:11:46

我想说你实现的解决方案看起来很Pythonic;话虽如此,types.SimpleNamespace(记录在此处) 已经封装了这个功能:

from types import SimpleNamespace
p = SimpleNamespace(name = "John Smith", age = 23)
print(p)

I'd say that the solution you implemented looks pretty Pythonic; that being said, types.SimpleNamespace (documented here) already wraps this functionality:

from types import SimpleNamespace
p = SimpleNamespace(name = "John Smith", age = 23)
print(p)
转瞬即逝 2024-09-18 14:11:46

我不认为创建“匿名”类/实例有什么问题。在一行代码中通过简单的函数调用来创建一个通常非常方便。我个人使用这样的东西:

def make_class( *args, **attributes ):
    """With fixed inability of using 'name' and 'bases' attributes ;)"""
    if len(args) == 2:
        name, bases = args
    elif len(args) == 1:
        name, bases = args[0], (object, )
    elif not args:
        name, bases = "AnonymousClass", (object, )
    return type( name, bases, attributes )

obj = make_class( something = "some value" )()
print obj.something

对于创建虚拟对象,它工作得很好。 Namedtuple 还可以,但是它是不可变的,这有时会很不方便。字典是......好吧,字典,但在某些情况下,您必须传递定义了 __getattr__ 的内容,而不是 __getitem__

我不知道它是否是Pythonic,但它有时会加快速度,对我来说,这是使用它的充分理由(有时)。

I don't see anything wrong with creating "anonymous" classes/instances. It's often very convienient to create one with simple function call in one line of code. I personally use something like this:

def make_class( *args, **attributes ):
    """With fixed inability of using 'name' and 'bases' attributes ;)"""
    if len(args) == 2:
        name, bases = args
    elif len(args) == 1:
        name, bases = args[0], (object, )
    elif not args:
        name, bases = "AnonymousClass", (object, )
    return type( name, bases, attributes )

obj = make_class( something = "some value" )()
print obj.something

For creating dummy objects it works just fine. Namedtuple is ok, but is immutable, which can be inconvenient at times. And dictionary is... well, a dictionary, but there are situations when you have to pass something with __getattr__ defined, instead of __getitem__.

I don't know whether it's pythonic or not, but it sometimes speeds things up and for me it's good enough reason to use it (sometimes).

世界如花海般美丽 2024-09-18 14:11:46

来自 Python IAQ

从 Python 2.3 开始,您可以使用以下语法

dict(a=1, b=2, c=3, dee=4)

就我而言,这已经足够好了。在Python 2.3之前我使用单行函数

def Dict(**dict): 返回字典

From the Python IAQ:

As of Python 2.3 you can use the syntax

dict(a=1, b=2, c=3, dee=4)

which is good enough as far as I'm concerned. Before Python 2.3 I used the one-line function

def Dict(**dict): return dict
愿与i 2024-09-18 14:11:46

我认为对象字面量在 JavaScript 中有意义有两个原因:

  1. 在 JavaScript 中,对象是创建具有字符串索引属性的“事物”的唯一方法。在 Python 中,正如另一个答案中所述,字典类型可以做到这一点。

  2. JavaScript 的对象系统是基于原型的。 JavaScript 中没有类这样的东西(尽管它会在未来的版本中出现)——对象具有原型对象而不是类。因此,通过文字“从无到有”创建一个对象是很自然的,因为所有对象只需要内置的根对象作为原型。在Python 中,每个对象都有一个类——您应该将对象用于具有多个实例的事物,而不仅仅是一次性的。

因此,对象字面量不是 Pythonic,但它们是 JavaScripthonic。

I think object literals make sense in JavaScript for two reasons:

  1. In JavaScript, objects are only way to create a “thing” with string-index properties. In Python, as noted in another answer, the dictionary type does that.

  2. JavaScript‘s object system is prototype-based. There’s no such thing as a class in JavaScript (although it‘s coming in a future version) — objects have prototype objects instead of classes. Thus it’s natural to create an object “from nothing”, via a literal, because all objects only require the built-in root object as a prototype. In Python, every object has a class — you’re sort of expected to use objects for things where you’d have multiple instances, rather than just for one-offs.

Thus no, object literals aren’t Pythonic, but they are JavaScripthonic.

楠木可依 2024-09-18 14:11:46

对于大多数情况来说,一个简单的字典就足够了。

如果您正在寻找与您为字面情况指定的 API 类似的 API,您仍然可以使用字典并简单地覆盖特殊的 __getattr__ 函数:

class CustomDict(dict):
    def __getattr__(self, name):
        return self[name]

p = CustomDict(user='James', location='Earth')
print p.user
print p.location

注意:请记住,与命名元组相反,字段是未经验证,你有责任确保你的论点是合理的。字典中允许使用诸如 p['def'] = 'something' 之类的参数,但您无法通过 p.def 访问它们。

A simple dictionary should be enough for most cases.

If you are looking for a similar API to the one you indicated for the literal case, you can still use dictionaries and simply override the special __getattr__ function:

class CustomDict(dict):
    def __getattr__(self, name):
        return self[name]

p = CustomDict(user='James', location='Earth')
print p.user
print p.location

Note: Keep in mind though that contrary to namedtuples, fields are not validated and you are in charge of making sure your arguments are sane. Arguments such as p['def'] = 'something' are tolerated inside a dictionary but you will not be able to access them via p.def.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文