Last active
August 29, 2015 14:21
-
-
Save ovidiucs/03d4021c94abb0d05b30 to your computer and use it in GitHub Desktop.
Explaining Classes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MyClass(object): | |
"""A simple class example""" | |
# Class OBJECTS support two kinds of operations | |
# 1. Attribute reference | |
# 2. Instantiation | |
i = 12345 | |
def something(self): | |
print 'printing - hello world' | |
return "returning - Hi" | |
# Class instantiation uses function notation | |
# The instantiation operation is below - aka - "Calling a class object" | |
x = MyClass() | |
y = MyClass() | |
# The above creates a new instance of the class and assigns this object to the local | |
# variables x and y | |
# MyClass.i AND MyClass.f are valid attribute references | |
# MyClass.i returns function object | |
print 80*'=' | |
print "x is at {0}\ny is at {1}\nMyClass is at {2} \nCall x.something() returns : {3}\n" \ | |
"x.something is a: {4}\nCall y.something() returns : {5}\n" \ | |
"y.something is a: {6}".format(x,y,MyClass(), x.something(), x.something, y.something(), y.something) | |
print 80*'=' | |
# x is at <__main__.MyClass object at 0x7ffa5ce8f050> | |
# y is at <__main__.MyClass object at 0x7ffa5cea8290> | |
# MyClass is at <__main__.MyClass object at 0x7ffa5cea82d0> | |
# Call x.something() returns : Hi | |
# x.something is a: <bound method MyClass.something of <__main__.MyClass object at 0x7ffa5ce8f050>> | |
# Call y.something() returns : Hi | |
# y.something is a: <bound method MyClass.something of <__main__.MyClass object at 0x7ffa5cea8290>> | |
# ================ | |
# Class ATTRIBUTES can also be assigned to, so you can change the value of MyClass.i by assignment | |
x.i = 54321 | |
y.i = 1000 | |
# 54321 1000 12345 | |
print x.i, y.i, MyClass.i | |
# Classes create objects. The special method __init__() create objects with | |
# instances customized to a specific initial state | |
class AnotherClass(object): | |
def __init__(self): | |
self.data = [] | |
# When we instantiate the above class it will automatically invoke __init__() | |
# for the newly created class instance | |
print 80*'=' | |
x1 = AnotherClass() | |
y1 = AnotherClass() | |
print x1.data | |
x1.data = [1,1,1,3,3,3] | |
y1.data = [3,3,3,1,1,1] | |
# [1, 1, 1, 3, 3, 3] [3, 3, 3, 1, 1, 1] | |
print x1.data, y1.data | |
# The __init__ method may have arguments for greater flexibilty | |
class AClass(object): | |
def __init__(self,num1,num2): | |
self.add = num1 + num2 | |
# TypeError: __init__() takes exactly 3 arguments (1 given) | |
# x2 = AClass() | |
x2 = AClass(3,4) | |
# 7 | |
print x2.add, type(x2), type(x2.add) | |
# ================ | |
# Instance Objects | |
# The only operations understood by instance objects are attribute references. | |
# Two kinds of valid attribute names: | |
# 1. Data attributes | |
# 2. Methods | |
# 1. Corresponds to "instance variables" | |
# - They need not be declared like local variables | |
# - They spring into existence when they are first assigned to | |
x.counter = 1 | |
print 80*'-' | |
while x.counter < 10: | |
x.counter = x.counter * 2 | |
# 16 | |
# ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', | |
# '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', ' | |
# __sizeof__', '__str__', '__subclasshook__', '__weakref__', 'counter', 'i', 'something'] | |
print x.counter, dir(x) | |
del x.counter | |
# 2. A METHOD is a function that "belongs to" an object | |
# - not unique to class instances (list objects have "append", "insert", "remove", ... etc. | |
# x.something is a valid method reference since MyClass.f is a function, x.1 is not. | |
# x.something is not the same thing as MyClass.f - it's a method object, not a FUNCTION object | |
# ================ | |
# Method objects | |
# Usually a method is called right after it is BOUND | |
#x.something() | |
# - It is not necessary to call a method right away | |
# - x.something is a METHOD OBJECT. It can be stored away and called at a LATER time | |
xs = x.something | |
print 80*'-' | |
if True: | |
print "Condition is true and I'm calling the method {0}".format(xs()) | |
# xs was CALLED without an argument | |
# the OBJECT is passed as the first arguments of the function | |
# when an instace attribute is referenced that isn't a data attribute, | |
# its calss is searched. If the names denotes a VALID class attribute that is a FUNCTION object | |
# a method object is created by pointing to the instance object | |
# ================ | |
# Class and instance variables | |
# Instance variables - DATA unique to each INSTANCE | |
# Class variables - for attributes and methods shared by ALL instances of the class | |
class Dog(object): | |
kind = 'canine' # class variable shared by all instances | |
def __init__(self, dogname): | |
self.name = dogname # instance variable unique to each instance | |
d1 = Dog('Fido') # unique to d1 | |
d2 = Dog('Lassie') # unique to d2 | |
# Fido Lassie canine canine | |
print d1.name, d2.name, d1.kind, d2.kind | |
# ================ | |
# Adding tricks to DOG class | |
class DogWithTricks(): | |
kind = 'canine' # class variable shared by all instances | |
# tricks = [] # INCORRECT - a single list shared by all DogWithTricks instances | |
def __init__(self, dogname): | |
self.name = dogname # instance variable unique to each instance | |
self.tricks = [] # create a new empty list for EACH dog | |
# correct use | |
def add_trick(self,trick): | |
self.tricks.append(trick) | |
d3 = DogWithTricks('Frodo') | |
d3.add_trick('play dead') | |
d3.add_trick('rollover') | |
# Frodo is the dog name and it knows ['play dead', 'rollover'] tricks | |
print "\n{0} is the dog name and it knows {1} tricks".format(d3.name,d3.tricks) | |
# Methods may call other methods by using method attributes of the self argument: | |
class Bag(object): | |
def __init__(self): | |
self.data = [] | |
def add(self,x): | |
self.data.append(x) | |
def addtwice(self,x): | |
self.add(x) | |
self.add(x) | |
bag1 = Bag() | |
bag1.add('gem') | |
bag1.addtwice('cascaval') | |
print "In punga am {0}".format(bag1.data) | |
# Methods may reference global names in the same way as ordinary functions | |
# It is not necessary that the function definition is textually enclosed | |
# in the class definition: assigning a function object to a local variable in the class is also ok. | |
# ================ | |
# Inheritance | |
class BaseClassName(object): | |
pass | |
class DerivedClassName(BaseClassName): | |
#<statement-1> | |
#. | |
#. | |
#. | |
#<statement-N> | |
pass | |
# When the class object is constructed, the base class is remembered. | |
# This is used for resolving attribute references. If a requested attributed is not found in the class, the | |
# search proceeds to look in the base class | |
# DERIVED classs MAY override methods of their base class | |
# Built-in functions that work with inheritance: | |
# 1. isinstance() to check an instance type isinstance(obj, int) will be True only if obj.__class__ is int | |
# 2. issubclass() to check class inheritance issubclass(bool, int) is True since bool is a subclass of int | |
# ================ | |
# Multiple Inheritance | |
# Old style classes : the only rule is depth-first, left-to-right. | |
# Private variables and Class-local References | |
# name prefixed with an underscore (e.g. _spam) | |
# should be treated as a non-public part of the API | |
# (whether it is a function, a method or a data member) | |
# to avoid name clashes of names with names defined by subclasses | |
# Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) | |
# is textually replaced with _classname__spam, where classname is the current class name with leading | |
# underscore(s) stripped | |
class Mapping(object): | |
def __init__(self, iterable): | |
self.items_list = [] | |
self.__update(iterable) | |
def update(self, iterable): | |
for item in iterable: | |
self.items_list.append(item) | |
__update = update # private copy of original update() method | |
class MappingSubClass(Mapping): | |
def update(self, keys, values): | |
# provide new signature for update() | |
# but does not break __init__() | |
for item in zip(keys, values): | |
self.items_list.append(item) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment