Access to personal use only, please correct me if wrong also.
Object-oriented programming is a programming design . The objects as basic program unit , an object contains data and operational data of the function .
This design idea is to come from nature. Because in nature, class (Class) and Example (Instance) concept is very natural. Class is an abstract concept, for example, we define a class athletes: Class-Player, refers to the concept of the athletes, and instances (Instance) is one concrete Player, for example: Jordan, Durant they are specific.
Programming experience knows, object-oriented three characteristics: encapsulation , inheritance , polymorphism .
Examples of classes and
Class is abstract template. For example, the Player class. Is a concrete example of objects, each has the same methods.
The definition of class
Keyword
class
, followed by the class name (capitalized), and finally (Object) . He can indicate which class is inherited, if not appropriate, on the choice ofobject
the class, because it is so kind of ancestors .class Player(object): pass
Create an instance of
With a function call similar, here it is the class name () operation.
# 创建实例1 player1 = Player() # 创建实例2 player2 = Player()
Binding Properties
By creating
__init__.py
method,self
representatives instance itself.class Player(object): def __init__(self, name, age): self.name = name self.age = age
Obtaining property by way of an object. Properties
# 创建实例1 player1 = Player("Jordan", 45) # 获取属性 name = player1.name age = player1.age
Package
Now, we know that instances can have these attributes. Directly within the class definition of access to the data functions , so that they "data" to package up. And the method is a function of the class.
Implementation of a print name, age
class Player(object): def __init__(self, name, age): self.name = name self.age = age def print_name_age(self): print("%s, %d"%(self.name, self.age)) player1 = Player("Jack", "30") print(player1.print_name_age())
From a caller's point of view, as long as when I create an instance of the input
name
,age
. And the method is called, get what I want. How to achieve specific class inside, I do not need to manage.
restriction of visit
In the foregoing classes and instances, we learned that inside the class may have attributes and methods. And the external code may also free to modify the properties of an instance. In fact, this is not safe , and we should avoid such operations. That is, take this variable changed from public to private.
Property privatization
In Python, using two underscores
__
can represent private property. Continued improvement of our Player class.class Player(object): def __init__(self, name, age): self.__name = name self.__age = age def print_name_age(self): return "%s, %d" % (self.__name, self.__age) player1 = Player("Jack", 30) print(player1.__name) # ERROR
After the property was privatized, it can not be acquired.
Acquire, modify privatization of property
Actually very simple, that is by
get
,set
methods. Now add to the classget_name
,get_age
method, andset_name
,set_age
method. Continue to change our Player class.class Player(object): def __init__(self, name, age): self.__name = name self.__age = age def get_name(self): return self.__name def get_age(self): return self.__age def set_age(self, age): self.__age = age def print_name_age(self): return "%s, %d" % (self.__name, self.__age) player1 = Player("Jack", 30) player1.set_age(100) print(player1.get_name()) # Jack print(player1.get_age()) # 100
Obviously, to achieve the change function. Could not add a method, you can directly modify, acquire, now add a method somewhat superfluous. Actually not, add methods aim is to make inspection of the parameters, to avoid passing invalid parameters.
Examples
def set_age(self, age): if 0 <= age <= 100: self.__age = age else: raise ValueError('bad score')
Of course, in the actual development projects, you will see the beginning of an underscore instance properties,
_name
. Access is accessible, but you see it as private.Finally, if you do not write
get
method can not be called, of course you can, because the Python interpreter__name
attribute becomes_Player__name
. But I suggest you forget. Not recommended
Inheritance and polymorphism
inherit
In the class definition would have said, all classes can inherit
object
the same class can inherit our own definition.For example, I define an
Animal
animal, the animal has arun()
method.If I write a dogs and cats, I'll be able to inherit this animal.
Examples
class Animal(object): def run(self): return "animal is running" class Dog(Animal): pass class Cat(Animal): pass
The benefits of inheritance: a subclass can get the full functionality of the parent class, meaning that dogs and cats already have a
run()
way to go.Based on the above examples, we go to calls.
dog = Dog() print(dog.run()) cat = Cat() print(cat.run()) # output animal is running animal is running
In order to comply with logic, we continue to change the code
class Animal(object): def run(self): return "animal is running" class Dog(Animal): def run(self): return "dog is running" class Cat(Animal): def run(self): return "cat is running" dog = Dog() print(dog.run()) cat = Cat() print(cat.run()) # output: dog is running cat is running
This is very clear, who is on the run.
When the sub-classes and superclasses are present in the same
run()
time method. Subclass the parent class has to cover.Polymorphism
For starters, polymorphism or a bit difficult to understand, we can only continue to strengthen through the program.
class Animal(object): def run(self): return "animal is running" class Dog(Animal): pass class Cat(Animal): def run(self): return "cat is running" dog = Dog() print(isinstance(dog, Dog)) print(isinstance(dog, Animal)) # output: True True
As can be seen from the above code
dog
belongs toDog
the type, and belongs toAnimal
the type. Similarly,cat
it is the same.When we pass an object, if the object has a
run()
method, on the implementation. If not, go call the parent classrun()
method. This is polymorphism.This is the dynamic languages, dynamic languages call an instance method, does not check the type, as long as there is a method, parameters correctly, you can call.
Continue to study
import json f = open('/path/to/file.json', 'r') print(json.load(f)) class Students(object): def __init__(self, strlist): self.strlist = strlist def read(self): return(self.strlist) s = Students('["Tim", "Bob", "Alice"]') print(json.load(s))
Since
f
the object has aread()
method, ands
objects haveread()
methods.Therefore, it can be considered that any object, as long as the
read()
method is called File-like Object , can be passedjson.load()
.
Get Object Information
Analyzing Object Type:
isinstance()
function, obtaining objecttype()
type: .Gets the object properties and methods:
dir()
function.Examples of attributes and class attributes
We mentioned earlier, you can use
__init__.py
methods instance attributes binding.Likewise, classes can have attributes. And classify all this property.
Examples
class Player(object): country = "chinese"
When we define a class attribute, although all classified, but it is instance of the class can access to.
The above test argument
p = Player() # 创建实例p print(p.country) # 打印country属性,因为实例并没有country属性,所以会继续查找类属性 print(Player.country) # 打印类属性 p.country = "small Japan" # 给实例绑定country属性 print(p.country) # 由于实例属性的优先级高于类属性,因此屏蔽了类的属性 print(Player.country) # 但是类属性并未消失。还是可以访问 del p.country # 删除实例绑定的属性之后 print(p.country) # 再去调用,就只能委屈得到类属性了。
Note: When the actual programming, do not for instance attributes and class attributes using the same in name .
Class Methods
As mentioned earlier instances have attributes and methods, there are the kind of attributes, there are also methods.
Examples
class Person(object): count = 0 @classmethod def how_many(cls): return cls.count def __init__(self, name): self.name = name Person.count = Person.count + 1 print(Person.how_many()) p1 = Person('Bob') print(Person.how_many())
It can be seen, by marking a @classmethod , which bind to
Person
the classes, instances, rather than class. The first parameter of the incoming class methods class itself, usually named as the parameter namecls
, the abovecls.count
actually equivalentPerson.count
.Because it is in the class calls rather than calling on the instance, therefore class method can not obtain any instance variables , you can only obtain a reference class .
__slots__
Because you can dynamically bound, so we need to limit, the method is used to limit the property instance. For example the following procedure:
class Student(object): __slots__ = ('name', 'age') s = Student() s.name = "Jack" s.age = 20 s.score = 90 # AttributeError
The above procedure can be seen: a tuple definition allows binding of the attribute name, since the score is not put
__slots__
in, it can not bind score property. If there Student have subclasses,slots
attributes defined subclasses has no effect.@property
We mentioned to restrict access to the front. Relationship between variables. We used
get
,set
method. It looks a bit complicated, not directly with the property so convenient.Python that there is no check both parameters, and variables can be accessed in a similar class attribute such a simple way? It exists.
Like decorator can dynamically add a function to the function for a class method, the same functions decorator.
Python's built-
@property
decorator is responsible for a way to become a property called in. For example, the following procedureclass Student(object): @property def score(self): return self._score @score.setter def score(self, value): if not isinstance(value, int): raise ValueError('score must be an integer!') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100!') self._score = value s = Student() s.score = 60 print(s.score)
@property
The role is to become a property getter method, just add@property
it at this time,@property
which in turn created another decorator@score.setter
responsible for a setter method becomes the property assignment, so we have a controllable properties operating. Look at the code,s.score = 60
the actual conversion iss.set_score(60)
,s.score
the actual converteds.get_score()
. So in fact, the essence or through getter and setter methods to achieve.Enum class
In some cases, a class object is limited and fixed , such as the season class, it has only four objects; planetary type, as long as the current 8 subjects; month class with the object 12, and a fixed finite Examples of such the class is called enumeration class .
Enumeration class that defines
Created by using Enum () function. The first parameter is the class name enumeration class, the second parameter is an enumeration value tuple format.
import enum Season = enum.Enum('Season', ('SPRING', 'SUMMER', 'FALL', 'WINTER'))
Access enumeration values
Each member has a name, value two properties.
# 直接访问指定枚举 print(Season.SPRING) # 访问枚举成员的变量名 print(Season.SPRING.name) # 访问枚举成员的值 print(Season.SPRING.value) # output: Season.SPRING SPRING 1
In addition, to improve a
__members__
property, which returns a dict dictionary.for name, member in Season.__members__.items(): print(name, '=>', member, ',', member.value) # output: SPRING => Season.SPRING , 1 SUMMER => Season.SUMMER , 2 FALL => Season.FALL , 3 WINTER => Season.WINTER , 4
type()
Mentioned earlier, type () function can view the type of variables, but if you want to use the type () directly view the type of a class of it? Consider the following code:
class Role: pass r = Role() # 查看变量r的类型 print(type(r)) # <class '__main__.Role'> # 查看Role类本身的类型 print(type(Role)) # <class 'type'>
Card can be seen from the above output, the class itself, Role type is type. This sentence a bit hard to pronounce, how to understand the type of Role class is type?
From the viewpoint of the Python interpreter, when the program using the class definition of class Role also understood to define a particular object (object class type), and the object is assigned to a variable Role. Therefore, the program using the class definition of all classes are instances of class type.
Python is actually allowed full type () function (equivalent to type the constructor function of the class) to create an object type, and because the instance of the class type is the class type may be used so Python () function to dynamically create a class. For example the following procedure:
def fn(self): print('fn函数') # 使用type()定义Dog类 Dog = type('Dog', (object,), dict(walk=fn, age=6)) # 创建Dog对象 d = Dog() # 分别查看d、Dog的类型 print(type(d)) print(type(Dog)) d.walk() print(Dog.age) #output: <class '__main__.Dog'> <class 'type'> fn函数 6
Use type () to specify parameters define three classes:
1, a parameter: class name created.
2, two parameters: a set of class inherits the parent class. Since Python supports multiple inheritance, so here tuple specify its multiple parent classes. Even though actually only a parent, but also need to use the tuple syntax (must be more than a comma).
3, three parameters: the class variables and methods for the class dictionary objects bound. Which is like a dictionary key variable or method name, if the dictionary's value is the value of the ordinary, it represents the class variables; if the value is a function of the dictionary, is the method.
Thus, line 5 Dog code defines a class that inherits the object class, the class also defines a walk () method and a variable age class.
Moto类
Metaclass is not difficult to understand, after reading the whole process, if you do not understand, then you do not learn.
Speaking in front of the type () function, when in fact it applies to dynamically create a relatively simple class, if you want to create complex class is required by MetaClass (classifiers) way.
Yuan class can be simply understood as the class is to create a class.
Defined metaclass
Need to make inheritance and type class, and the default naming convention is to make the class name to MetaClass the end. Moreover, the element need be defined and implemented
__new__()
methods (there must be a return value). Because the yuan class when the class is created, the__new__()
method will be called, used to generate a new class.# 定义Item元类,继承type class ItemMetaClass(type): # cls代表动态修改的类 # name代表动态修改的类名 # bases代表被动态修改的类的所有父类 # attr代表被动态修改的类的所有属性、方法组成的字典 def __new__(cls, name, bases, attrs): # 动态为该类添加一个cal_price方法 attrs['cal_price'] = lambda self: self.price * self.discount return type.__new__(cls, name, bases, attrs)
In the above procedure, when the target classes override this method to dynamically add a cal_price method.
Create a class metaclasses
# 定义Book类 class Book(metaclass=ItemMetaClass): __slots__ = ('name', 'price', '_discount') def __init__(self, name, price): self.name = name self.price = price @property def discount(self): return self._discount @discount.setter def discount(self, discount): self._discount = discount # 定义cellPhone类 class CellPhone(metaclass=ItemMetaClass): __slots__ = ('price', '_discount' ) def __init__(self, price): self.price = price @property def discount(self): return self._discount @discount.setter def discount(self, discount): self._discount = discount
The above program defines two classes CellPhone Book and, in the definition of two classes specify the type of information element, and therefore when the Python interpreter when creating these two classes, ItemMetaClass of
__new__
modifying this method will be called for two classes.So these two classes is still there cal_price () method definition. The following code is detected.
b = Book("Python基础教程", 89) b.discount = 0.75 # 创建Book对象的cal_price()方法 print(b.cal_price()) cp = CellPhone(2399) cp.discount = 0.85 # 创建CellPhone对象的cal_price()方法 print(cp.cal_price()) # output: 66.75 2039.1499999999999
From the point of view of the operation of the above results, by using a batch type metaclass can dynamically modify the program, they focus on some modifications. This feature is very useful when developing some basic framework, the program may need to have a common function for a certain number of dollars by using the class class add methods.