Object oriented programming in python

64
Object-oriented programming in Python Radosław Ganczarek

Transcript of Object oriented programming in python

Page 1: Object oriented programming in python

Object-oriented programming in Python

Radosław Ganczarek

Page 2: Object oriented programming in python

Important links

This presentation: http://bit.ly/1U6EFDDGist with examples: http://bit.ly/1fGkKIC

Page 3: Object oriented programming in python

Object-oriented programming

Page 4: Object oriented programming in python

Everything is an object?

Page 5: Object oriented programming in python

Don’t forget the diagrams...

Page 6: Object oriented programming in python

But hey, we are coding Python!

Page 7: Object oriented programming in python

Mr Chicken as a classclass Chicken(object): "Describes a chicken." def __init__(self, name): self.name = name def make_sounds(self): "Print chicken sound." print "squeaaaak!"

Page 8: Object oriented programming in python

But in the real world...class WorkflowProxy(object): def __init__(self, identity, f): self.identity = identity self.f = f

def __call__(self, decision, history, tracer): th = TaskHistory(history, self.identity) wd = WorkflowDecision(decision, self.identity, self.f) if tracer is None: return Proxy(th, wd) return TracingProxy(tracer, self.identity, th, wd)

Page 9: Object oriented programming in python

Let’s start!

Page 10: Object oriented programming in python

Basics

Page 11: Object oriented programming in python

Mr Chicken, welcome backclass Chicken(object): """Describes a chicken.""" def __init__(self, name): self.name = name

def make_sounds(self): """Print chicken sound.""" print "squeaaaak!"

Page 12: Object oriented programming in python

What can we do with this class?# Make and use instancemr_chicken = Chicken('mr')mr_chicken.make_sounds()

# See docsprint Chicken.__doc__print Chicken.make_sounds.__doc__

# Weird, but worksChicken.make_sounds(mr_chicken)

Page 13: Object oriented programming in python

Attributesclass Shop(object): first_shop_in_town = None

def __init__(self, name): if not Shop.first_shop_in_town: Shop.first_shop_in_town = name self.name = name

shop1 = Shop('ladybug')shop2 = Shop('frog')print Shop.first_shop_in_town

Page 14: Object oriented programming in python

Lesson, lesson!Write a class Game, which will contain information about a football game. You should be abble to:● add new game (names of teams, results, etc.)● update game with new data, assuming you’ve created game

object before game started and you want to add new goals during the match (but some data, like teams, won’t change)

● check number of games added so far● (not mandatory) write simple console interface for managing

games

Page 15: Object oriented programming in python

More on attributes

Page 16: Object oriented programming in python

Dynamic attribute accessmr_chicken = Chicken('mr')mr_chicken.driver_license_number = '666999666'

for field in ['name', 'tshirt_size', 'driver_license_number']: if hasattr(mr_chicken, field): if field == 'driver_license_number': print "Chrickens are not allowed to drive!" delattr(mr_chicken, field) else: print '{0}: {1}'.format(field, getattr(mr_chicken, field)) else: print "Empty field {}".format(field) setattr(mr_chicken, field, 'here be nothing')

Page 17: Object oriented programming in python

Magic methods

__getattr____setattr____delattr____getattr__ vs __getattribute__

Page 18: Object oriented programming in python

Let’s see all attributes!mr_chicken = Chicken('mr')

print mr_chicken.__dict__

print dir(mr_chicken)

print Chicken.__dict__

Page 19: Object oriented programming in python

Meet the garbage man!

del mr_chicken # It's not deletion of object!

Page 20: Object oriented programming in python

Lesson, lesson!Write class Roman, which will implement conversion from roman number system. Save numbers you convert once so that you don’t have to compute them second time.Example usage:r = Roman()

print r.xvi

>>> 16

Hint: http://bit.ly/1K37YSN

Page 21: Object oriented programming in python

Inheritance

Page 22: Object oriented programming in python

class Article(object): title = None body = None

def __init__(self, **kwargs): for key, value in kwargs.iteritems(): if hasattr(self, key): setattr(self, key, value)

def publish(self): print self.title print self.body

Page 23: Object oriented programming in python

class SponsoredArticle(Article): company = None product = None

def publish(self): print "A nice article from {0}, creators of {1}!".format( self.company, self.product, ) super(SponsoredArticle, self).publish()

docker_howto = Article(title="Docker HOWTO", body="Just use docker")google_it = SponsoredArticle(title="Google it!", body="To google or not to google.", company="Alphabet", product="Google")

print google_it.company

Page 24: Object oriented programming in python

Finding outprint isinstance(google_it, Article)print isinstance(docker_howto, SponsoredArticle)print issubclass(SponsoredArticle, Article)print issubclass(SponsoredArticle, object)print repr(google_it) # __repr__print str(docker_howto) # __str__print docker_howto.__class__.__name__

Page 25: Object oriented programming in python

Hide and protectclass A(object): _name = None __id = None

class B(A): passa = A()A._name = 'Daisy'print B._name # Avoidb = B()print b._name # Avoidprint b.__id # Error!print b._A__id # Not error, but still bad

Page 26: Object oriented programming in python

Lesson, lesson!Write a a couple (at least two) of classes inherinting from Game to store results of other games, that will store different data (e.g. number of sets in volleyball, names instead of teams in tennis, number of red cards in football).Update and overload methods.Hide information that should not be seen

Page 27: Object oriented programming in python

Operators

Page 28: Object oriented programming in python

Overloading operatorsUnary:__pos__ +x__neg__ -x__abs__ abs(x)__round__ round(x)__floor__ math.floor(x)__ceil__ math.ceil(x)

Binary:__add__ x + y__sub__ x - y__mul__ x * y__div__ x / y__mod__ x % y__pow__ x ** y__cmp__ *comparison

Page 29: Object oriented programming in python

Exampleclass Railway(object): def __init__(self, length, income): self.length = length self.income = income

def __cmp__(self, other): if abs(self.length - other.length) <= 100: return cmp(self.income, other.income) return cmp(self.length, other.length)

def __add__(self, other): return Railway( self.length + other.length, self.income + other.income - 100, )

Page 30: Object oriented programming in python

Examplepkp = Railway(1000, 200)pendolino = Railway(2000, 100)tgv = Railway(1100, 100)

print pkp < tgvprint tgv < pendolinopkp_pendolino = pkp + pendolinoprint pkp_pendolino.__dict__

Page 31: Object oriented programming in python

Lesson, lesson!

Create class Team for football teams.Make it possible to compare teams.Implement operator * for teams. Its result will be Game object.Try to do similar stuff for other kinds of games you implemented.

Page 32: Object oriented programming in python

Decoratorsclass Options(object): loaded_files = [] options = None

@staticmethod def parse(filename): <parse file>

def load_options(self, filename): self.options=dict(self.parse(filename)) Options.loaded_files.append(filename)

@classmethod def was_analyzed(cls, filename):

return filename in cls.loaded_files

@property def option_keys(self): return self.options.keys()

o = Options()o.load_options('/etc/profile')print Options.was_analyzed('/etc/profile')print o.option_keys

Page 33: Object oriented programming in python

Identitya = 1b = 1print a is ba = 257b = 257print a is b

l1 = [1,2,3]l2 = [1,2,3]print l1 is l2print id(l1)

__repr__ vs __str__ vs __hash__

Page 34: Object oriented programming in python

Everything is an object, even a class

Page 35: Object oriented programming in python

Everything is an objecta = 1

print dir(a)

class BetterInt(int):

pass

Chicken = type('Chicken', (object, ), {'name': None})

print type(Chicken)

an_object = object()

Page 36: Object oriented programming in python

Types

Page 37: Object oriented programming in python

Type

Can’t be changedOperations supportedValues supportedMutabilityComparison is available for all objects (but it doesn’t mean it’s sane)https://docs.python.org/2/library/stdtypes.html

Page 38: Object oriented programming in python

Small types

import typesmy_one = types.NoneType() # Won't work!my_not_implemented = types.NotImplementedType() # Won't work!

Type Instances Boolean value

types.NoneType None False

types.NotImplementedType NotImplemented True

Page 39: Object oriented programming in python

Numeric types

Protocol: all arithmetic and bitwise operatorsProtocol for bool: logic operatorsProtocol for real: floor, ceil, round, trunc

Page 40: Object oriented programming in python

Iteratorsfrom random import randintclass RandomIterator(object): count = 0

def __iter__(self): return self

def next(self): if self.count > 7: raise StopIteration() self.count += 1 return randint(0, 256)

randomiter = (randint(0, 256) for _ in range(7))

print RandomIterator().next()print randomiter.next()

Page 41: Object oriented programming in python

Context Managersclass ReadConfigFile(object): def __init__(self, filename): self.filename = filename

def _parse(self): return {'hostname': self.fd.read()}

def __enter__(self): self.fd = open(self.filename, 'r') return self._parse()

def __exit__(self, exc_type, exc_val, exc_tb): self.fd.close()

with ReadConfigFile('/etc/hostname') as options: print options['hostname']

Page 42: Object oriented programming in python

Lesson, lesson!

1. Implement iterator with numbers written as roman numerals.

2. Create context manager WorldCup that works like this

with WorldCup(): game = team1 * team2 print type(game) # WorldCupGame

game2 = team1 * team2print type(game) # Game

hint - use global

Page 43: Object oriented programming in python

Nice, but what’s with it “everything is an object”?

Page 44: Object oriented programming in python

Callable objects

FunctionsMethodsClass typesBuilt-in functionsBuilt-in methodsGenerators...

def function(x=1): "Blah" a = 1

print dir(function)print function.func_codeprint function.func_defaultsprint function.func_globalsprint function.func_name

function = lambda x: xprint function.func_name

Page 45: Object oriented programming in python

Internal objects

CodeFrameTracebackSliceStatic methodClass method

Page 46: Object oriented programming in python

Internal class manipulation

Page 47: Object oriented programming in python

__new__ vs __init__

Is a static methodTakes class as first argumentReturns a classIs ran before __init__Creates class

Is an instance methodTakes instance as first argumentShould return NoneIs ran after __new__Customises instance

Page 48: Object oriented programming in python

Metaclassesdef metacls(name, bases, dict): for key, value in dict.items(): if isinstance(value, int): dict[key] = float(value) return type(name, bases, dict)

class A(object): a = 1 __metaclass__ = metacls

a = A()print a.a

When creating class A instead of running:type( 'A', (object,), {'a': 1})this is run:metacls( 'A', (object,), {'a': 1},)

Page 49: Object oriented programming in python

Faking roots

Remember isinstance and issubclass? You can trick them with:__isinstancecheck____subclasscheck__

Page 50: Object oriented programming in python

Faking behaviour

Behave like:- function- dict- collection- list

__call____*item____len__ __contains____*slice__

Page 51: Object oriented programming in python

Lesson, lesson!

Modify class Team to contain a list of all players with their numbers. Make it possible to access a player of number n by calling: t[n].Add metaclass to Game classes, that will take first players from both teams and save them in additional field “captains” as a mapping between team name and captain name.

Page 52: Object oriented programming in python

Not tired of attributes? Here’s more!

Page 53: Object oriented programming in python

Descriptors (__getattribute__)a.xa.__dict__['x']type(x).__dict__['x']...

A.xA.__dict__['x']...

a.xtype(a).__dict__['x'].__get__( a, type(a),)

A.xA.__dict__['x'].__get__( None, A,)

Page 54: Object oriented programming in python

Kinds of descriptors

Data descriptorNon-data descriptorRead-only data descriptor

__get__, __set____get____get__, __set__ (raises AtrributeError)

__delete__

Page 55: Object oriented programming in python

Quirksclass A(object):

@propertydef get(self):

return 1

@staticmethoddef show():

return 'a'

a = A()a.__dict__['get'] = 2print a.geta.__dict__['show'] = 'b'print a.show

Page 56: Object oriented programming in python

More descriptorsfrom collections import defaultdict

class AttrStat(object):_stats = defaultdict(int)

def __init__(self, value):

self.value = value

def __get__(self, obj, objtype): self._stats['get'] += 1 return self.value

def __set__(self, obj, val): self._stats['set'] += 1 self.value = val

class A(object):x = AttrStat(1)

a = A()print a.xa.x = 100print a.xprint dict(AttrStat._stats)

Page 57: Object oriented programming in python

Remember property decorator?

It’s a descriptor!

property(fget, fset, fdel, doc)

property.getter

property.setter

property.deleter

Page 58: Object oriented programming in python

Slotsfrom sys import getsizeofclass A(object):

def __init__(self): self.x = 1

class B(object):__slots__ = ('x', )def __init__(self):

self.x = 1print getsizeof(A), getsizeof(B)print getsizeof(A()), getsizeof(B())

Page 59: Object oriented programming in python

Important notes

Inheriting class without slots will still make its __dict__ accessibleYou cant add new attributesSlots use descriptors (is it surprising???)__slots__ is not shared to subclassesoverloaded slot is not accessible

Page 60: Object oriented programming in python

Abstract Base classes

ABCMetaregisterabstractmethodabstractproperty

Page 61: Object oriented programming in python

ABC Examplefrom abc import *

class Animal(object): __metaclass__ = ABCMeta @abstractmethod def make_sounds(self): pass @abstractproperty def appearance(self): pass

class Dog(object): fur_color = None def make_sounds(self): print "Bark!" def appearance(self): print '{} dog'.format(self.fur_color) class Chicken(object): feather_colour = None def make_sounds(self): print "squeak!" def appearance(self): print "{} chicken".format(self.feather_colour) Animal.register(Dog)Animal.register(Chicken)

Page 62: Object oriented programming in python

MRO

Page 63: Object oriented programming in python

Lesson, lesson!

Implement abstract class for game classes.

Make descriptor RomanNumber that works like this

class A(object): n = RomanNumber(8)

a = A()print a.n# VIIIa.n = 19print a.n# XIX

Page 64: Object oriented programming in python

Thank you!

Radosław GanczarekSenior Python Developer @ STX Next

email: [email protected]: @dreamwalker_in