classes Flashcards
memorize details about python classes
super()
super(class, instance) -> returns object up the MRO list with its attributes and methods
- Basic: Allows you to call a method on a base class within the overridden method on a subclass
- Complicated: returns an actual object with attributes and methods based on where it was used.
- Appears to go backward through the MRO to find a method or attribute in the case of complex inheritances.
- Typically, ‘class’ is the class where it was used, and instance is ‘self’
isinstance()
issubclass()
isinstance(instance, class)
- determines if an instance of a class has the stated class anywhere in its inheritance chain
issubclass(class, class)
- determines if an actual class inherits from another class
always True:
isinstance(obj, cls) == issubclass(type(obj), cls)
class dunders
- __bases__
- __subclasses__()
- __mro__ # new style classes only
How a class is created
a class is a code block, will accept any valid python code.
- When a new class is found, python makes a namespace for the block
- assignments are made to the new namespace
- the namespace is used to populate a new type object, representing the class
the new type has 3 things
- the name of the class
- the base classes
- the namespace dictionary
Identical:
class Example(int):
spam = 'eggs'
Example = type(‘Example’, (int,), {‘spam’:’eggs’})
Calling type directly is troublesome and doesn’t appear worth it
Metaclasses
- a class to create classes
done by subclassing ‘type’ and overriding any methods necessary, usually __new__() or __init__()
type takes three arguments, so will __init__()
class SimpleMetaClass(type):
def \_\_init\_\_(cls, name, bases, attrs): print(name) super(SimpleMetaClass, cls).\_\_init\_\_(name, bases, attrs)
This will print out the name of every class it encounters.
class Example(metaclass=SimpleMetaClass):
pass
declaring this class (not creating an instance)
will produce:
Example
Plugin Framework
Used as applications get large. Accomodates flexibilitiy. Things are needed.
- define a place where plugins can be used.
- Should be obvious how to implement individual plugins
- Framework needs to provide a way to access the found plugins
So, they should extend a base class - the point where plugins are plugged in.
What’s a plugin look like?
makes a place for the class inheriting this to mount plugins, if it already has one, mounts the plugin on its parent class.
class PluginMount(type):
‘’’
Place this metaclass on any standard Python class to turn it into a plugin mount point. All subclasses will be automatically registered as plugins.
‘’’
def __init__(cls, name, bases, attrs):
if not hasattr(cls, ‘plugins’):
cls.plugins = []
else:
cls.plugins.append(cls)
Controlling the namespace
- use __prepare__ method on a metaclass
- rather than getting the namespace dictionary as an argument, it is responsible for returning that dictionary.
- often used with an ordered dictionary so attributes can be stored in the order they were declared
- @classmethod
- __prepare__(cls, name, bases): return OrderedDict()
Attribute methods
- getattr() retrieves the value of an attribute
- setattr() sets it
- delattr() deletes it
These can be used to access attributes without knowing their names.
Properties
Properties allow attributes to be powered by methods that can use python logic
use the “@property” decorator
It forces the function to be called whenever the attributes name is accessed as an attribute
(why not just use a method?)
class Person: def \_\_init\_\_(self, first, last): self.first = first self.last = last @property def name(self): return '%s, %s' % (self.last, self.first)
To add a setter, you need a method of the same name (name, in this case), decorated by @name.setter
@name.deleter does what’s expected
Descriptors
p 129
Problem with properties is that they require all methods to be defined as part of the class definition.
Allows definition of an object to behave like a property, regardless of the class it’s assigned on. Basically assigns a class to an attribute.
both methods and properties are just descriptors behind the scenes
This example always returns the current time. __get__ provides an up-to-date value.
class CurrentTime:
def __get__(self, instance, owner):
return datetime.datetime.now()
class Example:
time=CurrentTime()
__set__() works similarly, but can only be performed on instances. (maybe create a list and log events and times, etc).
Methods
Unbound
when accessing a function on a class, it is an unbound method - doesn’t need an instance
Callable like any other function, but it carries some class info with it.
Bound
Backed by the same function, but the method now recieves the instance as its first argument
**since bound methods accept an instance as the first argument, method binding can be faked by explicitly passing an instance to an unbound method. Handy when passing functions around as callbacks.
Class Methods
p 134
using @classmethod decorator, passes class as first argument to the method, even if the method was called on an instance.
Any method decorated like this will have the class passed as its first argument, including all subclasses.
it is bound, since the method is bound on the class it was called from.
You can also define the method in a metaclass. The class will be the first argument. The method will not be available on instances of classes that inherit form the metaclass, but the class will have the method.
Static Methods
p134
For when the class is more information than is necessary for the method to do its job. the @staticmethod decorator ensures the method won’t receive any implicit arguments at any time.
Assigning functions to classes and instances
works how you’d expect I think. assign an arbitrary function to a class attribute and that class can execute the new function - if it requires an argument the class can’t execute it, if it doesn’t, it works just like a static method.
A function assigned to an instance attribute works just like a static method as well.