In Python, what is the difference between an object and a dictionary?
Asked Answered
E

5

30

After an object has been created, I can add and remove slots at will, as I can do with a dictionary. Even methods are just objects stored in slots, so I probably can add methods to a dictionary as well.

Is there something I can do with a (non-dictionary) object that I could never do with a dictionary? Or is it possible to set up a dictionary that completely looks like an object of a certain class?

This question is not about how they are created, but about how I can use them afterwards. Links or references are appreciated.

Eldoria answered 19/8, 2011 at 8:58 Comment(3)
A dictionary is just an object, why do you expect it to behave differently from other objects?Excrescent
I clarified my question.Eldoria
You have to access a dictionary differently, (or else subclass it and implement __getattr__, but then you're just doing exactly what a class is doing), but it can do anything a class can do, since a class is just a dictionary internally. It's just easier to use. The reference at the end of my answer explains the why of objects and classes in Python.Dialect
U
16

When you call member functions of an object, they get passed the object itself as a first parameter. This way they can modify properties of the object they belong to:

class Counter(object):
   def __init__(self):
      self.num = 0

   def inc(self):
      self.num += 1

count = Counter()
count.inc()

If you just store a bunch of functions in a dict, they will get no such support. You have to pass the dict around manually to achieve the same effect:

def Counter_inc(d):
   d['num'] += 1

def Counter_create():
   d = {
      'num': 0,
      'inc': Counter_inc,
   }
   return d

count = Counter_create()
count['inc'](count)

As you can see while it is possible, it is much more clumsy. While you can emulate many features of object with raw dicts, having special language support for objects makes them easier to use.

Also there are features that directly use an objects type information, like for example isinstance(), which cannot easily be replicated with raw dicts.

Usia answered 19/8, 2011 at 9:20 Comment(3)
Afaik, a method is an object that has a function and an object it is bound to. So I could create a method from a function and a dictionary, and store it in that very dictionary, thus have a dict with a real method.Eldoria
" like for example isinstance(), which cannot easily be replicated with raw dicts" not easily, or not at all?Eldoria
@Arian: I think you'd need to manually add some "type information" into your dict, like d['__typeinfo'] = "Counter_class" and then use that to distinguish the "types" of your dicts. But the builtin isinstance() will still say that all your objects are of type dict and nothing more specific. In the end you probably can implement most features of classes/objects on the basis of dicts, but they will not play together seamlessly with the existing classes and support functions.Usia
D
20

After an object has been created, I can add and remove slots at will, as I can do with a dictionary. Even methods are just objects stored in slots,

Be careful saying slots -- __slots__ has a specific meaning in Python.

so I probably can add methods to a dictionary as well.

foo = {}
foo.bar = 1

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

Not by default, you'd need to subclass it -- but then you're using a class. Instead, put the function in the dictionary:

def bar():
    return 1

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

Is there something I can do with an object that I could never do with a dictionary?

This question actually has a false premise -- dictionaries are objects, so anything you do with a dictionary you are doing with an object. For the rest of this answer, I'll pretend you mean "user defined class" when you say "object".

No, there is nothing you can do with a user-defined class you can't do with a dictionary. Classes are even implemented with a dictionary.

class Foo(object):
    pass

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

Anything you can do with a class in Python you can do without one, with more work (and code which is much harder to understand, use, and maintain). It's even been said that Python classes are just syntactic sugar for dictionaries.

A very similar question was asked recently as Do I need to learn about objects, or can I save time and just learn dictionaries? I think my answer to that is also relevant here.

Dialect answered 19/8, 2011 at 9:7 Comment(2)
How can classes be implemented as dictionaries, and dictionary be objects? Isn't that rather circular? What's actually going on under the hood?Sealy
@ionsme It is circular. Under the hood, some of the core built-in objects, like dictionaries, implemented in the C layer in CPython, are special -- but semantically it's still true.Dialect
U
16

When you call member functions of an object, they get passed the object itself as a first parameter. This way they can modify properties of the object they belong to:

class Counter(object):
   def __init__(self):
      self.num = 0

   def inc(self):
      self.num += 1

count = Counter()
count.inc()

If you just store a bunch of functions in a dict, they will get no such support. You have to pass the dict around manually to achieve the same effect:

def Counter_inc(d):
   d['num'] += 1

def Counter_create():
   d = {
      'num': 0,
      'inc': Counter_inc,
   }
   return d

count = Counter_create()
count['inc'](count)

As you can see while it is possible, it is much more clumsy. While you can emulate many features of object with raw dicts, having special language support for objects makes them easier to use.

Also there are features that directly use an objects type information, like for example isinstance(), which cannot easily be replicated with raw dicts.

Usia answered 19/8, 2011 at 9:20 Comment(3)
Afaik, a method is an object that has a function and an object it is bound to. So I could create a method from a function and a dictionary, and store it in that very dictionary, thus have a dict with a real method.Eldoria
" like for example isinstance(), which cannot easily be replicated with raw dicts" not easily, or not at all?Eldoria
@Arian: I think you'd need to manually add some "type information" into your dict, like d['__typeinfo'] = "Counter_class" and then use that to distinguish the "types" of your dicts. But the builtin isinstance() will still say that all your objects are of type dict and nothing more specific. In the end you probably can implement most features of classes/objects on the basis of dicts, but they will not play together seamlessly with the existing classes and support functions.Usia
L
3

The other answers hold some ground, but I'd like to add that you can't subclass or instantiate specific dictionaries.

class A(object): pass
class B(A): pass
a = A()

A = {}
B = ???
a = ???

So, dictionaries are objects and objects are implemented mainly with dictionaries (although I don't know the specifics), but they are different tools for different jobs.

Lingo answered 19/8, 2011 at 9:18 Comment(2)
You can subclass dict, and you can't subclass an instance of object, so this behavior seems congruent to me? The equivalent of subclassing a particular dictionary would be to mydict.copy().update('new': 'stuff')Dialect
It's not the same, though, otherwise object orientation in Lua would be much simpler than it really is.Lingo
G
1

I think you ask about

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

vs

class SomeClass:
    def some_method(self, par1, par2):
        return par1+par2

o2=SomeClass()
o2.some_method(1, 2)

? If so, i think the main differnce from practical point of view, is that o2.some_method takes self as first param but o1["some_method"] not.

Graniah answered 19/8, 2011 at 9:9 Comment(1)
You could write the method to take self as the first parameter, you'd just have to pass it manually: self = {"some_method": lambda self, par1, par2: par1+par2} and self["some_method"](self, 1, 2). Of course, you couldn't call all of the dictionaries self, you'd have to use different names.Dialect
F
1

Object is a {} created from the class:

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}

Dictionary is a {} not created from the class:

student2 = { 'name': 'Kevin', age: 15 } # student2 is a dictionary
print(student2) # prints {'name': 'Kevin', 'age': 15}
Fosterfosterage answered 27/1, 2018 at 13:45 Comment(1)
If I print(address) all I get is Address object. How can i inspect the object?Conifer

© 2022 - 2024 — McMap. All rights reserved.