object
is the standard base classclass EmptyClass(object):
"""
This is an empty class called EmptyClass
"""
pass
Instances are created from classes
class Dog(object): """ This is an empty class called dog Think of it as the definition of a dog """ pass # My dog spot is the actual dog my_dog_spot = Dog()
Use isinstance()
to check if an object is an instance of specific classes
>>> isinstance(my_dog_spot, Dog) True
Class attributes are variables assigned statically with a class
class Car(object): """ This is a simple class called Car It has one class attribute, wheels """ wheels = 4
Attributes can be accessed in the class or in a class instance
>>> Car.wheels 4 >>> myCar.wheels 4
If a class attribute is changed, it affects all instances and children
>>> Car.wheels = 5 >>> myCar.wheels 5
>>> myCar.wheels = 3
>>> myCar.wheels
3
>>> Car.wheels
5
Methods are functions defined within a class
class Car(object): """ This is a simple class called Car It has one class attribute and one method """ wheels = 4 def wheel_count(self): return self.wheels>>> myCar = Car() >>> myCar.wheel_count() 4
self
is the first argument to a standard method
self
is a reference to the current instance
self
is a convention and can technically be called anything
The instance is automatically passed as the first argument to a method call
class SampleClass(object): """ A simple class to show self """ def know_thyself(self): print("I am %s" % self)>>> myInstance = SampleClass() >>> myInstance.know_thyself() I am <__main__.SampleClass object at 0x7fc70f98d990>
A special method __init__()
is used to customize a class
Generally used for validation and to set instance attributes
Takes arguments, but can not return anything
class Car(object): wheels = 4 def __init__(self, fuel='gas', doors=4): self.fuel_type = fuel self.door_count = doors>>> myTeslaModel3 = Car('electric') >>> myTeslaModel3.fuel_type 'electric' >>> myTeslaModel3.door_count 4
In standard methods, self
can be used to access attributes
class Car(object): wheels = 4 def __init__(self, fuel='gas', doors=4): self.fuel_type = fuel self.door_count = doors def get_groceries(self): if self.door_count > 2: return True else: return False>>> myTeslaModel3 = Car('electric') >>> myTeslaModel3.get_groceries() True
getattr()
provides another way to get attributesgetattr(object, name[, default])
getattr(object, name)
is equivalent to object.name
>>> getattr(myTeslaModel3, 'fuel_type')
'electric'
>>> getattr(myTeslaModel3, 'flux_cap_type')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Car' object has no attribute 'flux_cap_type'
>>> getattr(myTeslaModel3, 'flux_cap_type', 'Mr. Fusion')
'Mr. Fusion'
hasattr()
provides a way to to check if an attribute existshasattr(object, name)
>>> hasattr(myTeslaModel3, 'fuel_type')
True
>>> hasattr(myTeslaModel3, 'flux_cap_type')
False
setattr()
provides a way to set attributessetattr(object, name, value)
object.name = value
>>> setattr(myTeslaModel3, 'flux_cap_type', 'Mr. Fusion')
>>> myTeslaModel3.flux_cap_type
'Mr. Fusion'
delattr()
provides a way to delete attributesdelattr(object, name)
del object.name
>>> delattr(myTeslaModel3, 'flux_cap_type')
>>> hasattr(myTeslaModel3, 'flux_cap_type')
False
Class methods operate on a class rather than an instance
The first argument is the class object, cls
by convention
Create a class method with the classmethod()
decorator
class Car(object): def __init__(self, fuel='gas', doors=4): self.fuel_type = fuel self.door_count = doors @classmethod def station_wagon(cls, fuel='gas'): return cls(fuel, 5)>>> myWagon = Car.station_wagon() >>> myWagon.door_count 5
Static methods do not operate on instances or classes
Regular functions included in a class
Useful for related utility functions
Create a static method with the staticmethod()
decorator
class Car(object): @staticmethod def honk_horn(): print("Beep!\a")>>> myTeslaModel3 = Car() >>> myTeslaModel3.honk_horn() Beep! >>> Car.honk_horn() Beep!
Properties allow attributes to be backed by methods
Create a property with the property()
decorator
import time class Product(object): @property def serial(self): if not hasattr(self, '_serial'): self._serial = time.time() return self._serial>>> widget = Product() >>> widget.serial 1474583633.99423 >>> widget.serial 1474583633.99423
Properties also provide a way to call a method for assignment
import time class Product(object): @property def serial(self): if not hasattr(self, '_serial'): self._serial = time.time() return self._serial @serial.setter def serial(self, value): if not isinstance(value, float): raise TypeError('serial must be a float') self._serial = value
The setter method will be called during assignment
>>> widget = Product()
>>> widget.serial = "ABC"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in serial
TypeError: serial must be a float
>>> widget.serial = 1.0
>>> widget.serial
1.0
class Fruit(object):
"""
Fruit base class
"""
def eat(self):
print("Yum!")
class Banana(Fruit):
"""
Banana subclass
"""
def peel(self):
print("Banana's are aPEELing!")
Subclasses inherit methods and attributes from base classes
>>> myBanana = Banana() >>> myBanana.eat() # Provided in Fruit base class Yum! >>> myBanana.peel() # Provided in Banana subclass class Banana's are aPEELing! >>> isinstance(myBanana, Banana) True >>> isinstance(myBanana, Fruit) True
Use issubclass()
to check inheritance
>>> issubclass(Banana, Fruit)
True
class Car(object):
wheels = 4
def __init__(self, fuel='gas', doors=4):
self.fuel_type = fuel
self.door_count = doors
class TeslaModel3(Car):
def __init__(self, battery=65):
Car.__init__(self, 'electric', 4)
self.battery_size = battery
super()
is used to access ancestor methods and attributes
class TeslaModel3(Car):
def __init__(self, battery=65):
super(TeslaModel3, self).__init__(self, 'electric', 4)
self.battery_size = battery
class Car(object):
def contact_dealer(self):
raise NotImplementedError
class TeslaModel3(Car):
def contact_dealer(self):
print("Call 1-888-51-TESLA")
>>> Car().contact_dealer()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in contact_dealer
NotImplementedError
>>> TeslaModel3().contact_dealer()
Call 1-888-51-TESLA
Classes can have multiple parents
Can get complicated, use rarely and sparingly
class Car(object): wheels = 4 class Tesla(object): def contact_dealer(self): print("Call 1-888-51-TESLA") class TeslaModel3(Car, Tesla): pass>>> TeslaModel3.wheels 4 >>> TeslaModel3().contact_dealer() Call 1-888-51-TESLA
__iter__()
that returns itselfdict.keys()
behaves like dict.iterkeys()
did in Python 2list
>>> myDict = {'a' : 1, 'b' : 2, 'c' : 3}
>>> myDict.keys()
dict_keys(['a', 'b', 'c'])
>>> list(myDict.keys())
['a', 'b', 'c']
__iter__()
__iter__()
will automatically return an iteratorclass range2(object):
def __init__(self, start, end):
self.start = start
self.end = end
def __iter__(self):
current = self.start
while current < self.end:
yield current
current += 1
>>> numbers = range2(1, 10) >>> numbers <__main__.range2 object at 0x7fc389a77cc0> >>> list(numbers) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(numbers) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> numbers.__iter__() <generator object range2.__iter__ at 0x7fc38b0b6410> >>> numbers.__iter__() <generator object range2.__iter__ at 0x7fc38b0b6620> >>> numbersIterator = numbers.__iter__() >>> numbersIterator.__iter__() is numbersIterator True