[Tutor] dict.get() vs. dict.get

Steven D'Aprano steve at pearwood.info
Fri Aug 1 05:36:58 CEST 2014


On Thu, Jul 31, 2014 at 07:56:23PM -0700, memilanuk wrote:
> What is the difference between dict.get() and dict.get as shown in the 
> code below:

Depending on how you look at it, the difference is either "nothing at 
all", or "the round brackets ()". And I'm not trying to be funny.

Experimenting at the interactive interpreter may shed some light on 
this:

py> d = {1: 'a', 2: 'b'}
py> d.get
<built-in method get of dict object at 0xb7bd224c>


So dict.get returns the "get" method of dict objects, but without 
actually calling it yet. It doesn't get called until add 
parentheses (round brackets) to it:

py> method = d.get  # Don't call it yet, just grab the method.
py> print method
<built-in method get of dict object at 0xb7bd224c>
py> method(2)  # Now call it.
'b'
py> method(3, 'ZZZ')
'ZZZ'


So adding brackets to the method object calls it. We can do the same 
with *any* function or method, not just "get":

py> len
<built-in function len>
py> len([])
0


Now, what's the difference between d.get and dict.get? The first one is 
*bound* to an instance, in this case d, while the second one is not. Let 
me explain.

Most methods operate on a specific instance. These two calls to "get" do 
different things, because the instance they are calling on are 
different:


instance1 = {1: "a", 2: "b"}
instance2 = {1: "AAA", 2: "BBB"}
instance1.get(1)  # returns "a"
instance2.get(1)  # returns "AAA"


Pretty obvious, right? And the same thing happens if you grab the 
method, it remembers which instance it came from:


method = instance2.get  # Don't call the method yet!
method(2)  # returns "BBB"



So far so good. But what happens if you access the method, not from an 
instance, but directly from the class?


method = dict.get  # comes from dict, not from instance1 or instance2


You still get a method, but now you get a method that doesn't know which 
instance to operate on. If the earlier examples were bound to an 
instance, this one is called an *unbound* method. So when you call it, 
you have to provide the instance first!


method(instance1, 2)  # returns "b"
method(instance2, 2)  # returns "BBB"


To look at it another way, when you define a method, you write it with a 
"self" argument:

class MyClass:
    def do_something(self, x, y, z):
        ...


instance = MyClass()
instance.do_something(x, y, z)


In this case, Python sees that you're calling the method from instance, 
and automatically provides that as the "self" argument. But if you do 
this:


MyClass.do_something


there's no "self" yet, so you have to manually provide it.

And that's the difference between bound and unbound methods.


Does help explain what is going on? Feel free to ask more questions if 
needed.




-- 
Steven


More information about the Tutor mailing list