Python - 'if name in dict:' OR 'try:/except:' I'm writing some OO Python and I would like to know which of these methods is more pythonic, or which is generally better, or faster. This is an accessor for an attribute which is a dictionary.

Method 1: if/else

def GetSlot(self, slot_name):
    if slot_name in self.Slots:
        return self.Slots[slot_name]
    else:
        return None


Method 2: try/except

def GetSlot(self, slot_name):
    try:
        return self.Slots[slot_name]
    except KeyError:
        return None


I understand that using try/except is better use of duck typing, but will this make a positive impact on performance?
It depends.

Mostly, it depends on whether it'll generally be in the dictionary or not. If it's nearly always in the dictionary, then the try/except method would win out, while if it's in there as often as not, then checking would be somewhat faster.

However, python already anticipated your need. There's a better option:

def GetSlot(self, slot_name):
    return self.Slots.get(slot_name)


All mappings support get, which has a default optional argument that defaults to None. This should be the best option. However, that said...


GetSlot is not a PEP8-compliant name. It should be get_slot.
self.Slots should probably be self.slots.
NOTE: Since you confirmed in a comment that you are in fact using externally defined names, I think it is best practice to follow those names as well as their naming conventions when appropriate.
This should probably not be a method at all. In python, accessor functions are somewhat frowned upon. If you really need to do something like this, use properties. However, anything wanting to get slot_name from self.Slots should just use self.Slots.get(slot_name). Even if you're reaching into the object from outside. Java and other languages that advocate getter/setter methods do so because it later allows you to change how it is gotten, but Python is better and doesn't require workarounds like this to influence how you access a variable. Read more here.


A note on Python getters and setters

Python descriptors are a powerful tool. It's not actually an object, it's a protocol of how python retrieves variables when they're used as object attributes. The classic example is python's property, but in truth methods on a class are also descriptors. An object implements this protocol by having __get__, __set__ or __delete__ methods on it. Not all are required for every type of descriptors - please follow the link for in-depth classification and usages. 

What this all means in practice is that python objects can change how they are retrieved. This is impossible in languages like Java, which can cause engineering issues. 

Let's first figure out why people use getters and setters in Java, because the reasons they have are quite important.

So I have a class with an attribute that I want to expose to the public for usage.

(NOTE: Java users please don't take offense. I'm writing just Python here since I've honestly never used Java. All my knowledge of it is second-hand at best.)

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.distance_to_orgin = pythagoras(x, y)
# Later...
instance = Point(a, b)
instance.distance_to_orgin 


Now, everyone can access it. So I publish my library, and everyone's code works fine. 

But then, I get a better idea - every point already knows it's x and y, so I can always calculate the distance_to_orgin if I need it. 

In Java, I now have a problem. Because to calculate something on retrieval, I NEED a function - but everyone accesses it by attribute access. I cannot make this change in a backwards compatible manner. So, programmers learn to make getter and setter methods. Compare to before:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.distance_to_orgin = pythagoras(x, y)

    def get_distance_to_orgin(self):
        return self.distance_to_orgin


# Later...
instance = Point(a, b)
instance.get_distance_to_orgin()


Now, if I want to change how it works, I can just write a different get_distance_to_orgin method and I can make the change - fully backwards compatible!

So why isn't this a problem in Python?

Because we have descriptors. In 99.9% of cases, the builtin property() does everything you want. I can just amend my class definition like this:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y
        # self._distance_to_orgin = pythagoras(x, y) No longer needed

    @property
    def distance_to_orgin(self):
        return pythagoras(self.x, self.y)

# Later...
instance = Point(a, b)
instance.distance_to_orgin


And the external usage is exactly the same as it was at the very start, back when we were building a class in a naive way! 

So that is why getters and setters are important for many languages, but why we don't need them in Python.