Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Underscores in Python

Xuanyi
August 22, 2017

Underscores in Python

Underscores don't have meanings (for the most part) in python. But we often give it meaning by convention. In this talk I explore the uses of underscores in Python.

This was presented at Sydney Python for August 2017. It was mostly presented on the terminal, and the code has been copied into a slide for clarity

Xuanyi

August 22, 2017
Tweet

More Decks by Xuanyi

Other Decks in Programming

Transcript

  1. _ def foo(): return 1, 2.0, "hello", [3,4,5], (6,7) _,

    x, _, y_, _, _ = foo() # x = 2.0 # y = [3,4,5] Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  2. _name class Foo: def __init__(self, x): self._x = x >>>

    f = Foo(1) >>> f._x # still accessible! 1 Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  3. _name A Gotcha: In mypkg.py: _x = "internal use only"

    x = "externally accessible variable" Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  4. _name A Gotcha: In mypkg.py: _x = "internal use only"

    x = "externally accessible variable" >>> from mypkg import * >>> x 'externally accessible variable' Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  5. _name A Gotcha: In mypkg.py: _x = "internal use only"

    x = "externally accessible variable" >>> from mypkg import * >>> x 'externally accessible variable' >>> _x Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name '_x' is not defined Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  6. _name A Gotcha: In mypkg.py: _x = "internal use only"

    x = "externally accessible variable" >>> from mypkg import * >>> x 'externally accessible variable' >>> _x Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name '_x' is not defined Avoid this! Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  7. __name class Foo: def __init__(self, x): self.__x = x Follow

    @chewxy on Twi<er. Tweet #sypy. It's mandatory
  8. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> f.__x Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  9. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> f.__x Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Foo' object has no attribute '__x' >>> Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  10. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> f.__x Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Foo' object has no attribute '__x' >>> WTF IS GOING ON?? Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  11. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> dir(f) ['_Foo__x', '__class__', '__dela<r__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__geta<ribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__seta<r__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] >>> Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  12. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> dir(f) ['_Foo__x', '__class__', '__dela<r__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__geta<ribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__seta<r__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] >>> Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  13. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> f._Foo__x 1 Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  14. __name class Foo: def __init__(self, x): self.__x = x def

    get_x(self): return self.__x >>> f = Foo("SyPy") >>> f.get_x() 'SyPy' >>> f.__x Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Foo' object has no attribute '__x' Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  15. __name class Foo: def __init__(self, x): self.__x = x >>>

    f = Foo(1) >>> dir(f) ['_Foo__x', '__class__', '__dela<r__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__geta<ribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__seta<r__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] >>> Name Mangling Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  16. Why Mangle Names? class Foo: def __init__(self, x): self.__x =

    x class Bar(Foo): def __init__(self, x): super().__init__(x+"1337") self.__x = x >>> b = Bar("SyPy") >>> dir(b) Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  17. Why Mangle Names? class Foo: def __init__(self, x): self.__x =

    x class Bar(Foo): def __init__(self, x): super().__init__(x+"1337") self.__x = x >>> b = Bar("SyPy") >>> dir(b) ['_Bar__x', '_Foo__x', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  18. Why Mangle Names? class Foo: def __init__(self, x): self.__x =

    x class Bar(Foo): def __init__(self, x): super().__init__(x+"1337") self.__x = x >>> b = Bar("SyPy") >>> dir(b) ['_Bar__x', '_Foo__x', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  19. Why Mangle Names? class Foo: def __init__(self, x): self.__x =

    x class Bar(Foo): def __init__(self, x): super().__init__(x+"1337") self.__x = x >>> b = Bar("SyPy") >>> b._Bar__x 'SyPy' >>> b._Foo__x 'SyPy1337' Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  20. Name Mangling NaughZness _Foo__x = 'SyPy still rocks' class Foo:

    def get_x(self): return __x >>> f = Foo() Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  21. Name Mangling NaughZness _Foo__x = 'SyPy still rocks' class Foo:

    def get_x(self): return __x >>> f = Foo() >>> f.get_x() 'SyPy still rocks' Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  22. Name Mangling NaughZness _Foo__x = 'SyPy still rocks' class Foo:

    def get_x(self): return __x >>> f = Foo() >>> f.get_x() 'SyPy still rocks' Python will mangle any name that starts with __ Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  23. __name__ class Foo: def __init__(self, x): self.x = x def

    __add__(self, other): return self.x + other >>> f = Foo(1) >>> f + 1 2 Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  24. AutomaZc DifferenZaZon class Value(object): def __init__(self, v, d): self.v =

    v self.d = d def __mul__(self, other): other = promote(other) return Value(self.v * other.v, self.d*other.v + self.v*other.d) def __rmul__(self, other): return Constant(other) * self def __repr__(self): return repr(self.v) def promote(value): return value if isinstance(value, Value) else Value(value,1) Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory
  25. AutomaZc DifferenZaZon For context: d(x2)/dx = 2x >>> x =

    promote(3) >>> y = x * x >>> y 9 >>> y.d 6 With a bit more jiggering you get full proper automaZc parZal derivaZves Follow @chewxy on Twi<er. Tweet #sypy. It's mandatory