【问题标题】:In Python, what is the difference between an object and a dictionary?在 Python 中,对象和字典有什么区别?
【发布时间】:2011-10-30 11:01:46
【问题描述】:

创建对象后,我可以随意添加和删除插槽,就像使用字典一样。甚至方法也只是存储在槽中的对象,所以我可能也可以将方法添加到字典中。

有没有我可以用字典做不到的(非字典)对象做的事情? 或者是否可以建立一个完全像某个类的对象的字典?

这个问题不是关于它们是如何创建的,而是关于我以后如何使用它们。链接或参考表示赞赏。

【问题讨论】:

  • 字典只是一个对象,为什么你期望它的行为与其他对象不同?
  • 我澄清了我的问题。
  • 你必须以不同的方式访问字典,(或者子类化它并实现__getattr__,但是你只是在做一个类正在做的事情),但它可以做任何类可以做的事情做,因为一个类在内部只是一个字典。它更容易使用。我的答案末尾的参考解释了 Python 中对象和类的为什么

标签: python object-model


【解决方案1】:

创建对象后,我可以随意添加和删除插槽,就像使用字典一样。甚至方法也只是存储在槽中的对象,

小心说插槽 -- __slots__ has a specific meaning in Python.

所以我可能也可以将方法添加到字典中。

foo = {}
foo.bar = 1

AttributeError: 'dict' object has no attribute 'bar'

默认情况下不是,您需要对其进行子类化——但是您使用的是一个类。相反,将函数放入字典中:

def bar():
    return 1

foo['bar'] = bar
foo['baz'] = lambda: 1

我可以用一个对象做一些我不能用字典做的事情吗?

这个问题实际上有一个错误的前提——字典是对象,所以你用字典做的任何事情你都是用一个对象。对于这个答案的其余部分,当你说“对象”时,我会假装你的意思是“用户定义的类”。

不,你可以用用户定义的类做任何你不能用字典做的事情。类甚至是用字典来实现的。

class Foo(object):
    pass

print Foo.__dict__
# {'__dict__': <attribute '__dict__' of 'Foo' objects>, '__module__': '__main__', 
#      '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}

任何你可以用 Python 中的类做的事情,你可以不用一个类来做,需要更多的工作(以及更难理解、使用和维护的代码)。甚至有人说 Python 类只是字典的语法糖。

最近有人问了一个非常相似的问题Do I need to learn about objects, or can I save time and just learn dictionaries? 我认为我对此的回答在这里也很相关。

【讨论】:

    【解决方案2】:

    当您调用对象的成员函数时,它们会作为第一个参数传递对象本身。这样他们就可以修改他们所属对象的属性:

    class Counter(object):
       def __init__(self):
          self.num = 0
    
       def inc(self):
          self.num += 1
    
    count = Counter()
    count.inc()
    

    如果您只是将一堆函数存储在 dict 中,它们将得不到这样的支持。您必须手动传递 dict 才能达到相同的效果:

    def Counter_inc(d):
       d['num'] += 1
    
    def Counter_create():
       d = {
          'num': 0,
          'inc': Counter_inc,
       }
       return d
    
    count = Counter_create()
    count['inc'](count)
    

    正如您所看到的,虽然它是可能的,但它要笨拙得多。虽然您可以使用原始 dict 模拟对象的许多功能,但对对象具有特殊的语言支持会使它们更易于使用。

    还有一些功能直接使用对象类型信息,例如 isinstance(),这些功能无法通过原始字典轻松复制。

    【讨论】:

    • Afaik,方法是一个对象,它具有函数和绑定到的对象。所以我可以从一个函数和一个字典创建一个方法,并将它存储在那个字典中,这样就有一个带有真实方法的字典。
    • " 例如 isinstance(),不能轻易地用原始 dicts 复制”不容易,或者根本没有?
    • @Arian:我认为您需要手动将一些“类型信息”添加到您的字典中,例如d['__typeinfo'] = "Counter_class",然后使用它来区分您的字典的“类型”。但是内置的isinstance() 仍然会说你所有的对象都是dict 类型,没有更具体的了。最终你可能可以在 dicts 的基础上实现类/对象的大部分功能,但它们不能与现有的类和支持功能无缝配合。
    【解决方案3】:

    其他答案有一定的道理,但我想补充一点,您不能子类化或实例化特定的字典。

    class A(object): pass
    class B(A): pass
    a = A()
    
    A = {}
    B = ???
    a = ???
    

    所以,字典是对象,对象主要是用字典来实现的(虽然我不知道具体的),但它们是针对不同工作的不同工具。

    【讨论】:

    • 你可以继承dict,你不能继承object的实例,所以这种行为对我来说似乎是一致的?对特定字典进行子类化的等价物是 mydict.copy().update('new': 'stuff')
    • 虽然不一样,否则 Lua 中的面向对象会比实际简单得多。
    【解决方案4】:

    我想你问的是

    o1={"some_method": lambda par1, par2: par1+par2}
    o1["some_method"](1, 2)
    

    class SomeClass:
        def some_method(self, par1, par2):
            return par1+par2
    
    o2=SomeClass()
    o2.some_method(1, 2)
    

    ?如果是这样,我认为从实际角度来看,主要区别在于 o2.some_method 将 self 作为第一个参数,但 o1["some_method"] 不是。

    【讨论】:

    • 您可以编写将 self 作为第一个参数的方法,您只需手动传递它:self = {"some_method": lambda self, par1, par2: par1+par2}self["some_method"](self, 1, 2)。当然,你不能调用所有的字典self,你必须使用不同的名字。
    【解决方案5】:

    Object 是从该类创建的 {}:

    class Student:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    student1 = Student('John', 31) # student1 is an object
    print(student1) # does not print the expected result, we need to "convert" it to dictionary
    print(student1.__dict__) # prints {'name': 'John', 'age': 31}
    

    字典是不是从类创建的{}:

    student2 = { 'name': 'Kevin', age: 15 } # student2 is a dictionary
    print(student2) # prints {'name': 'Kevin', 'age': 15}
    

    【讨论】:

    • 如果我print(address) 我得到的只是Address object。如何检查对象?
    猜你喜欢
    • 2014-01-26
    • 2014-06-27
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 2012-03-14
    相关资源
    最近更新 更多