+ All Categories
Home > Software > Object.__class__.__dict__ - python object model and friends - with examples

Object.__class__.__dict__ - python object model and friends - with examples

Date post: 28-Nov-2014
Category:
Upload: robert-lujo
View: 462 times
Download: 1 times
Share this document with a friend
Description:
Python object model - advanced and some not so advanced features, lot of code examples: building blocks, objects, classes, functions, mutable and immutable, everything is an object, variables, global context, "executing" the module, standard types inheritance, multiple inheritance, mixins and mro, dynamic classes, metaclasses, property function and descriptors context managers & with, useful __methods__
31
object.__class__.__dict__ (python object model and friends) Robert Lujo, 2014
Transcript
Page 1: Object.__class__.__dict__ - python object model and friends - with examples

object.__class__.__dict__ !

(python object model and friends)

!Robert Lujo, 2014

Page 2: Object.__class__.__dict__ - python object model and friends - with examples

about me

• software

• professionally 17 y.

• python since 2.0, django since 0.96

• freelancer

• more info -> linkedin

Page 3: Object.__class__.__dict__ - python object model and friends - with examples

OOPobject oriented programming is a programming paradigm

concept of "objects"

a) "attributes" - data fields (state)

b) methods - associated functions (logic)

objects are instances of classes

https://en.wikipedia.org/wiki/Object-oriented_programming

Page 4: Object.__class__.__dict__ - python object model and friends - with examples

py - basic building blocks1. expressions

a + b!

2. functions - program logic, objects which can be "executed()"

lambda a,b: a+b

3. objects (classes)

Person()

4. "variables" - pointer to object

per = Person()

add = lambda a,b: a+b

5. commands

for per in person_list:

Page 5: Object.__class__.__dict__ - python object model and friends - with examples

everything is an objectx = None def add(a,b): return a+b class Person(object): … !for o in (1 , x, "", None, True, add, Person,Person(), Person().get_name ): print type(o),id(o),isinstance(o,object) !<type 'int'> 140699668384744 True <type 'NoneType'> 4546336056 True <type 'str'> 4546876680 True <type 'NoneType'> 4546336056 True <type 'bool'> 4546257024 True <type 'function'> 4548133304 True <type 'type'> 140699671469632 True <class '__main__.Person'> 4547839824 True <type 'instancemethod'> 4547596112 True !# https://docs.python.org/2.7/reference/datamodel.html

Page 6: Object.__class__.__dict__ - python object model and friends - with examples

object types• two kinds: mutable and immutable

• builtin immutable:

int long float complex

str/unicode bytes

tuple frozenset

• builtin mutable:

list dict

set byte-array

Page 7: Object.__class__.__dict__ - python object model and friends - with examples

immutable• immutable can not be changed :) - check functional paradigm

• important is to understand - "change" of variable is pointing to a new object

!>>> a = "test"

>>> b = "test"

>>> c = a

>>> id("test"), id("test")==id(a)==id(b)==id(c)

(4547809072, True)

>>> a += "ing" # is this changing an object?

>>> id(a), id(a)==id(b) # not really

(4547808736, False)

Page 8: Object.__class__.__dict__ - python object model and friends - with examples

mutable• supports changing the object in place

!>>> a, b = ["test"], ["test"]

>>> c = a

>>> id(a),id(b),id(c)

(4548130576, 4547733192, 4548130576)

>>> a.append(3) # promjena in-place

>>> id(a),id(b),id(c)

(4548130576, 4547733192, 4548130576)

!BUT - first member of both objects is immutable object and everywhere is the same!>>> id(a[0])==id(b[0])==id(c[0])

True

Page 9: Object.__class__.__dict__ - python object model and friends - with examples

global and local• every context has its own global and local variables - use functions globals(), locals()

• global variables are read-only, but again there is a difference between mutable and immutable

• global keyword !>>> g1, g2, g3 = 3, [3], 3 >>> id(g1), id(g2), id(g3) 2084115824 2523984 2084115824 !def fun(): # print g1 # produces: SyntaxWarning: name 'g1' is used prior to global declaration global g1 print g1, g2, g3 # g3 = 4 # if this is enabled then previous "print g3" and raises an Error print "fg1:", id(g1), id(g2), id(g3) g1 = 4 # change of global variable to new object g2.append(4) # although g2 variable is read-only, the object is NOT! print "fg2:", id(g1), id(g2), id(g3) # g1 has changed id locally and globally !>>> fun() 3 [3] 3 fg1: 2084115824 2523984 2084115824 fg2: 2084115812 2523984 2084115824 >>> print g1, g2, g3 4 [3, 4] 3 # change on g1 and g2 can be seen in object values >>> print id(g1), id(g2), id(g3) # the same as fg2: - function has changed global g1 2084115812 2523984 2084115824

Page 10: Object.__class__.__dict__ - python object model and friends - with examples

custom classes• custom classes are mutable

• all standard types can be inherited

• for immutable types we can add methods and attribues, but we can't change internal object state (e.g. change value of int object "3" to have value 4)

class Int(int):

def add2(self):

self.last = 2

return self+2

>>> x = Int(3) ; x.add2() ; x.last

5 2

Page 11: Object.__class__.__dict__ - python object model and friends - with examples

custom classes• it is much more interesting to inherit mutable objects - e.g.

!class JavascriptDict(dict):

def __getattr__(self, aname):

if aname in self:

return self[aname]

raise AttributeError("Attr %s not found. Use %s" % (

aname, ",".join(self.keys())))

!>>> d = JavascriptDict({"a" : 1, "b" : 2})

>>> d.a # calls d.__getattr__ - more details later …

1

>>> d.c

AttributeError: Attr c not found. Use a,b

Page 12: Object.__class__.__dict__ - python object model and friends - with examples

collections.*• from collections import OrderedDict!

• records the order the items are added

• from collections import Counter !>>> p = Counter(blue=2, red=3)

>>> p["green"]+=1

>>> p.most_common()

[('red', 3), ('blue', 2), ('green', 1)]

• from collections import defaultdict

Page 13: Object.__class__.__dict__ - python object model and friends - with examples

collections.namedtuple

>>> Person = namedtuple('Person', ['age', 'gender']) # returns class!

>>> p = Person(20, "m")

>>> p.age,p.gender -> 20, "m"

>>> age, gender = p

Page 14: Object.__class__.__dict__ - python object model and friends - with examples

misc std classes

• ABC - handy for isinstance(): numbers.Number, basestring

• currency type -> decimal.Decimal

• UserDict, UserList - mutable dict and list - for inheritance

Page 15: Object.__class__.__dict__ - python object model and friends - with examples

class, object and constructor

>>> type(int) <type 'type'> !>>> callable(int) True !# class/type is a "function" which returns a new object >>> x = int(); print x, id(x) 0 14069966838468 !# when and how was object "3" created? >>> int(3) == int.__call__(3) == 3 True !>>> id(int(3)) == id(int.__call__(3)) == id(3) True

Page 16: Object.__class__.__dict__ - python object model and friends - with examples

module loading & objects creation

• execution on loading of a module - white is not executed import sys

global_var = 3 # 2. maybe now object "3" is created? not IMHO.

def get_add_nr(nr): # 3. create a function object - add2 not created

def add2(a):

return a+nr

return add2

class Person(object): # 4. class object is getting created

CLS_ATTR = 22

class Age(object): # 4.2 inner class object is getting created

def get_age(self): # 4.2.1 creating function/object i.e. method

raise NotImplementedError()

def __init__(self,age,gender): # 4.3. creating function/object i.e. method

self.age, self.gender = age,gender

# dir() -> ['Person', 'get_add_nr', 'global_var', 'sys', '__file__', '__name__',…]

Page 17: Object.__class__.__dict__ - python object model and friends - with examples

multiple inheritance & mixins• one class inherits more than one class

• Mixin - popular usage of MI:

mixin is a class which contains a combination of methods from other classes, …encourages code reuse

!class FormMixin(object):

def init_fields(self):

for i, (fname, field) in enumerate(self.fields.iteritems()):

field.widget.attrs["placeholder"] = field.help_text

!class LoginForm(forms.Form, FormMixin):

def __init__(self, *args, **kwargs):

super(LoginForm, self).__init__(*args, **kwargs)

self.init_fields()

Page 18: Object.__class__.__dict__ - python object model and friends - with examples

MRO• method resolution order - which method will be called in the case of "method overloading"? !

class FormMixin(object):

def init_fields(self): … # 3. mixin method

!class Form(object):

def init_fields(self): … # 2. parent method

!class LoginForm(forms.Form, FormMixin):

def init_fields(self): … # 1. own method

def __init__(self, *args, **kwargs):

self.init_fields() # 1. own method - by default

super(LoginForm, self).init_fields() # 2. parent method

FormMixin.init_fields(self) # 3. mixing method

Page 19: Object.__class__.__dict__ - python object model and friends - with examples

obj/cls.__dict__• useful in some cases - not the same as result of dir(obj/cls)

• object.__dict__ - holds object attributes

• class.__dict__ - holds class attributes and methods

!class Person(object):

def __init__(self, name, dob):

self.dob, self.name = dob, name

!>>> per = Person("Bero", date(2000,1,1))

>>> per.__dict__ # object content

{'dob': datetime.date(2000, 1, 1), 'name': 'Bero'}

>>> per.__class__.__dict__ # class / same as: Person.__dict__

{'__dict__': …, '__module__': '__main__', '__weakref__': …, '__doc__': None, '__init__': <function __init__ at 0x1051ea230>}

Page 20: Object.__class__.__dict__ - python object model and friends - with examples

dynamic class creation• how to dynamically create an class, add attributes, methods … - runtime "code generator"

!def get_method(say):

def meth1(self): print "%ss" % say # the last "s" is not an error

return meth1

!Cat = type('Cat', (object,), # it looks a bit like Js?

{'meow': get_method('meow'),

'eat': get_method('eat')})

!>>> c = Cat()

>>> "Cat %s and %s" % (c.meow(), c.eat())

Cat meows and eats

Page 21: Object.__class__.__dict__ - python object model and friends - with examples

class decorator• function which gets class object and returns (changed or different) class object !

def add_age_method(cls):

def age_method(self): return date.today().year - self.dob.year

cls.age = age_method

return cos

!@add_age_method # is equal as: Person = add_age_method(Person)

class Person(object):

def __init__(self, dob):

self.dob = dob

>>> Person(date(2000,1,1)).age()

14

Page 22: Object.__class__.__dict__ - python object model and friends - with examples

metaclasses• The most complex but also the most powerfull to manage class creation

• django uses by implementing django.db.models.Model!

!class AddAgeMethodMeta(type):

def __new__(cls, name, bases, attrs):

def age_method(self): return date.today().year - self.dob.year

attrs["age"] = age_method

return super(AddAgeMethodMeta, cls).__new__(cls, name, bases, attrs)

!class Person(object):

__metaclass__ = AddAgeMethodMeta # python 2 way

def __init__(self, dob): self.dob = dob

!>>> Person(date(2000,1,1)).age()

14

Page 23: Object.__class__.__dict__ - python object model and friends - with examples

@property• property - very frequently used in other languages - Java, C#

• getter i setter - methods which "mimic" reading and changing an attribute

• python @property decorator / function - example given is using explicit function call:

class Person(object):

def __init__(self, dob): self.dob = dob

def get_age(self): return date.today().year - self.dob.year

def set_age(self, new_age):

self.dob = self.dob.replace(year=date.today().year - new_age)

def del_age(self): raise AttributeError("Age can not be deleted")

age = property(get_age, set_age, del_age,

"pydoc - Age in years - based on diff d.o.b. - today")

>>> p = Person(date(2000,1,1))

>>> p.age -> 14 # calls p.get_age()

>>> p.age = 15 # calls p.set_age(15)

>>> p.dob -> datetime.date(1999, 1, 1)

Page 24: Object.__class__.__dict__ - python object model and friends - with examples

descriptors• generalization of @property decorator - to have one single place for the same type of property data

• must be defined on class level!

• used for: methods, django related, django deferred … This example is simple - descriptors are more powerful: !

class AgeProperty(object):

def __get__(self,obj,objtype):

return date.today().year - obj.dob.year

!class Person(object):

age = AgeProperty() # must be defined on class level

def __init__(self, dob):

self.dob = dob

!>>> print Person(date(2000,1,1)).age # .age zone o.__class__.age.__get__(personobj)

14

Page 25: Object.__class__.__dict__ - python object model and friends - with examples

context managers• generalization of prepare and cleanup of objects using with command + __enter__ & __exit__

methods

• can be done with @contextlib.contextmanager decorator:

class Person(object):

DATA = {20 : dict(name="Katarina"), 23 : dict(name="Bero") }

def __init__(self, name): self.name = name

[email protected]

def per_load_and_save(id):

person = Person(**Person.DATA[id]) # load, on __enter__

yield person # send object in with blok (generator)

Person.DATA[id] = dict(name=person.name) # save, on __exit__

with per_load_and_save(id=23) as person:

print person.name

person.name = "Jo"

Page 26: Object.__class__.__dict__ - python object model and friends - with examples

__methods__• there is a huge number of reserved __methods__ - only some interesting/practical will be listed

• operators, commands and standard functions

"." __getattr__,__setattr__...

"for .. in" __iter__

[i] __getitem__,__setitem__...

"if .. in" __contains__

len() __len__

int()… __int__,...

"if "/bool() __nonzero__

+… __add__,...

|… __and__,...

>,[:]… ...

Page 27: Object.__class__.__dict__ - python object model and friends - with examples

obj. => __getattr__, ..• "." operator

• implementation using __getattr__, __setattr__, __delattr__

• much powerful alternative are __getattribute__ …. (doesn't check __dict__, "." recursion) !

class Person(object):

def __init__(self, dob): self.dob = dob

def __getattr__(self, aname):

if aname=="age": return date.today().year - self.dob.year

raise AttributeError("Attribute '%s' not found" % aname)

!>>> Person(date(2000,1,1)).age

14

!

Page 28: Object.__class__.__dict__ - python object model and friends - with examples

"for obj in" => __iter__• iteration -> implemenation of __iter__ method

• usually returns generator (yield), but can be implemented with an iterator too (__iter__ + next) !

class Person(object):

def __init__(self, name): self.name = name

!class PersonList(object):

def __init__(self, data): self.data = data

def __iter__(self): # yield -> function is a generator

for d in self.data:

yield Person(**d)

>>> for person in PersonList([dict(name="Katarina"), dict(name="Bero")]):

... print person.name,

Bero Katarina

!

Page 29: Object.__class__.__dict__ - python object model and friends - with examples

obj[i] => __getitem__, ..• [] operator - list or dictionary or …

• implementing using __getitem__, __setitem__, __delitem__ !

class Person(object):

def __init__(self, name): self.name = name

!class PersonList(object):

def __init__(self, data):

self.data = {d["name"] : Person(**d) for d in data}

def __getitem__(self, name):

return self.data[name]

!>>> per_list = PersonList([dict(name="Katarina"), dict(name="Bero")])

>>> print per_list["Bero"].name

Bero

Page 30: Object.__class__.__dict__ - python object model and friends - with examples

summary• python (IMHO)

• has an object model which suites all common use cases and lot of special ones

• hits a sweet spot when combining object and functional paradigm

• encourages creating a nice API, readable code and maintainable program structure

Page 31: Object.__class__.__dict__ - python object model and friends - with examples

aand … that's all folks!Thanks for the patience!

Questions?

Anyone?

!

[email protected]

@trebor74hr


Recommended