程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Introduction to Python zero foundation -9 class

編輯:Python

9. class

9.1 object-oriented

Before the beginning of this chapter , We need to know object-oriented (OOP,Object Oriented Programming) The concept of . If you have studied other object-oriented Programming language , Then you can skip this part .

object-oriented Is and Process oriented Relative . Take page going to dinner for example :

Process oriented That's true :

 Go to the canteen (...)
Buy Rice (...)
having dinner (...)

object-oriented That's true :

 page = The pig ()
page . Move ( canteen )
noodles = page . Buy ( noodles )
page . eat ( noodles )

You can see , An outstanding feature of object-oriented is Action object To achieve the function .

Class is One kind of thing Of abstract , Describes what a class of things should have attribute and function .

We can class As a attribute and function ( function ) The combination of . for example , Dog With age 、 weight 、 Name, etc attribute , Make a sound 、 having dinner 、 Running, etc function .

In reality, things are often Specifically Of , For example, the name of a piece is " Wang Wang ", Age 3 year , weight 10kg The little dog . This concrete thing we call class example .


There are some specific terms for object orientation , Such as class 、 Method 、 Data members, etc ,Python3 object-oriented | Novice tutorial (runoob.com). These concepts can be found by searching keywords such as object-oriented . This article does not explain these terms , Try to explain the role of classes through cases .

9.2 Define and use classes class

The simplest syntax for defining classes :

class Class name :
Some functions 、 sentence

Usually , We use Initialization function Defining a class attribute , And define some Function function Implementation class function .

Initialization function Is a name __init__() Special methods , You can have parameters and the first parameter is always self( By convention , It's not a grammatical rule ). If the initialization method is set , call Class name ( Parameters ) This method will be called automatically when .

self Parameters represent instances , The instance object is automatically passed in through the instance calling method as self Parameters . with self The method of parameters is often called Example method .

class Dog:
def __init__(self, name=" unknown ", age=0, weight=0):
self.name = name
self.age = age
self.weight = weight
def bark(self):
print(" Wang Wang Wang ")
def growup(self):
self.age += 1

After defining the class , The usage class is generally Create examples object , adopt example Object to operate on .

ww = Dog(" Wang Wang ",0,1) # Use the class name ( Parameters ), Create instance object
print(ww.age) # Use Instance object . attribute , Access properties
ww.growup() # Use instance objects . Method , Calling method .
# ww As self Parameters , Pass in growup(self) Method
ww.bark()
print(ww.age)

9.3 Inherit

9.3.1 Single inheritance

Class can inherit from other classes , What is inherited is called Base class ( Or parent ), A successor be called Derived class ( Subclass ). By inheriting subclasses, you can have methods and properties of the parent class . for example , above Dog A class is an animal , Then you can inherit Animal Class acquisition Animal Properties of , weight , Age etc. ; The way to have animals , Grow up, etc .

The benefits of this approach are less obvious when there are fewer classes , When there are more classes , For example, we continue to create cats , birds , fish … after , We can reduce a lot of duplicate code through inheritance .

The grammar of inheritance :

class Derived class ( Base class ):
Some sentences
class Animal:
def __init__(self,name=" unknown ", age=0, weight=0):
self.name = name
self.age = age
self.weight = weight
def growup(self):
self.age += 1
class Dog(Animal):
def __init__(self, name=" unknown ", age=0, weight=0):
super().__init__(name,age,weight)# Use super(). Call the superclass method
def bark(self):
print(" Wang Wang Wang ")
ww = Dog(" Wang Wang ",0,1)
print(ww.age)
ww.bark()
ww.growup() # growup Method Inherited from Animal
print(ww.age)
print(" Wang Wang Wang ")

notes :Python 3 It can be used directly super().xxx Instead of super(Class, self).xxx :


The execution of derived classes :

The execution process of the derived class definition is the same as that of the base class . When constructing class objects , The base class will be remembered . This information will be used to resolve property references : If requested Property not found in class , Search will Go to the base class to find . If the base class itself is derived from some other class , Then this rule will be applied recursively .

There is nothing special about the instantiation of derived classes : DerivedClassName()  A new instance of this class will be created . Method references will be resolved as follows : Search for the corresponding class properties , If necessary, search down the inheritance chain of the base class step by step , If a function object is generated, the method reference takes effect .

Derived classes may rewrite The method of its base class . Because methods do not have special permissions when calling other methods of the same object , So a base class method that calls another method defined in the same base class may eventually call a method that covers its derived class .

Overloaded methods in derived classes may actually want to extend rather than simply replace base class methods with the same name . There is a way to Simply call the base class method directly : That is to call  BaseClassName.methodname(self, arguments). Sometimes it's also useful for clients . ( Please note that only if this base class can be in global scope with  BaseClassName  You can use this method when the name of is accessed .)

Python There are two built-in functions that can be used for inheritance mechanisms :

  • Use  isinstance()  Come and check one Type of instance isinstance(obj, int)  Only in the  obj.__class__  by  int  Or one derived from  int  The class time of is  True.

  • Use  issubclass()  To check Class inheritance issubclass(bool, int)  by  True, because  bool  yes  int  Subclasses of . however ,issubclass(float, int)  by  False, because  float  No  int  Subclasses of .

9.3.2 Multiple inheritance

Python Also support multiple inheritance . however Rarely used , And it may cause name confusion , Not recommended .

The class definition statement with multiple base classes is as follows :

class Derived class ( Base class 1, Base class 2, Base class 3):
Some sentences
# Need to use Base class 1. Method To call base class methods

for example :

class A:
def __init__(self):
self.aname = 'a'
class B:
def __init__(self):
self.bname = 'b'
class C(A, B):
def __init__(self):
#super().__init__()
# If you use super(). Method () To call the parent method , The first eligible parent class will be found up in order
A.__init__(self)
B.__init__(self)
cc = C()
print(cc.aname, cc.bname)

For most applications , In the simplest case , You can think of the operation of searching for attributes inherited from the parent class as Depth first 、 From left to right , When there is overlap in the hierarchy, it will not search the same class twice . therefore , If a property is in  DerivedClassName  No , Then it will arrive  Base1  Search for it , then ( recursively ) To  Base1  Search for , If you can't find it there , Until then  Base2  Mid search , And so on .

The truth is a little more complicated than that ; The method parsing order changes dynamically to support the  super()  The cooperative call of . This is called subsequent method calls in some other multiple inheritance languages , It's better than in a single inheritance language super Call more powerful .

It is necessary to change the order dynamically , Because all cases of multiple inheritance show one or more diamond associations ( That is, at least one parent class can be accessed by the lowest class through multiple paths ). for example , All classes are inherited from  object, So any case of multiple inheritance provides more than one path to  object. To ensure that the base class is not accessed more than once , Dynamic algorithms can linearize the search order in a special way , Keep the left to right order specified by each class , Call each parent class only once , And keep it monotonous ( That is, a class can be subclassed without affecting the priority of its parent class ). To make a long story short , These features make it possible to design reliable and extensible classes with multiple inheritance . For more details , see also  The Python 2.3 Method Resolution Order | Python.org.

9.4 Class variables and instance variables

Instance variables It belongs to the example , Each instance has ,

Class variables Belong to category , All instances of the class share .

If the same property name appears in both instances and classes , Then the attribute search will give priority to Instance attributes .

class Dog:
kind = 'canine' # Class variables , All instances share
def __init__(self, name):
self.name = name # Instance variables , Each instance has its own
>>> d = Dog('Fido')
>>> e = Dog('Buddy')
>>> d.kind # All dogs share
'canine'
>>> e.kind # All dogs share
'canine'
>>> d.name # d alone possess
'Fido'
>>> e.name # e alone possess
'Buddy'

9.5 Private variables

python in No, similar java or C++ Use that way private Limited 、 Can only be accessed from the inside Private variables .

however , majority Python The code follows such a convention : Name with an underscore ( for example  _spam) It should be taken as API The non-public part of ( Whether it's a function 、 Method or data member ).

Name override :Python adopt   Name rewriting provides limited support for private variables . In any form  __spam  Identifier ( Underline with at least two prefixes , At most one suffix underline ) The text of will be replaced with  _classname__spam, among  classname  For the current class name without prefix underscores .

Name rewriting just modifies the name .

Name rewriting helps subclasses overload methods without breaking intra class method calls . for example :

class Mapping:
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):
# provides new signature for update()
# but does not break __init__()
for item in zip(keys, values):
self.items_list.append(item)

Even in  MappingSubclass  Introduced a  __update  There is no error in the case of identifiers , Because it will be in  Mapping  Class is replaced with  _Mapping__update  And in the  MappingSubclass  Class is replaced with  _MappingSubclass__update.

Please pay attention to pass it on to  exec()  or  eval()  The code will not consider the class name of the calling class as the current class ; This is similar to  global  The effect of the statement , So this effect is limited to code that is compiled in bytecode at the same time . The same restrictions apply to  getattr()setattr()  and  delattr(), And for  __dict__  A direct reference to .

9.6 Use empty classes to simulate C The structure of the body

Sometimes you need to use something like C Of “struct” This type of data , Bundle some named data items together . This situation is suitable for defining an empty class :

class Employee:
pass
john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000

9.7 iterator

Most containers can be used for Statement to iterate , As listing 、 Tuples 、 Dictionaries 、 String, etc.

for element in [1, 2, 3]:
print(element)
for element in (1, 2, 3):
print(element)
for key in {'one':1, 'two':2}:
print(key)
for char in "123":
print(char)
for line in open("myfile.txt"):
print(line, end='')

Behind the scenes ,for  Statement is called on the container object  iter(). This function returns a definition  __next__()  Iterator object for method ,__next__() Method will access the elements in the container one by one . When the elements are exhausted ,__next__()  Will lead to  StopIteration  Exception to notify termination  for  loop .

You can use  next()  Built in function to call  __next__()  Method ; This example shows how it works :

>>> s = 'abc'
>>> it = iter(s) # Return iterator object
>>> it
<str_iterator object at 0x10c90e650>
>>> next(it) # Use next() Equivalent to call it Of __next__() Method
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it) # Element exhaustion will cause StopIteration abnormal
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration

therefore , Just add... To the class __iter__ Method returns the iteration object , add __next__ Method return element , You can turn a custom class into an iterator , Then you can use it for Circulated .

class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def __next__(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> rev = Reverse('spam')
>>> iter(rev)
<__main__.Reverse object at 0x00A1DB50>
>>> for char in rev:
... print(char)
...
m
a
p
s

9.8 generator

9.8.1 generator

generator   Is a simple and powerful tool for creating iterators , It looks like a belt yield Function of , But it actually creates iterators .

During the call generator run , Every encounter yield Function will pause and save all current running information , return yield Value , And next time next() Method to continue from the current location .

An example of creating a generator is as follows :

def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'): # It works like an iterator
... print(char)
...
f
l
o
g

What can be done with generators can also be done with the class based iterators described in the previous section . But the generator is more compact , Because it will automatically create  __iter__()  and  __next__()  Method .

Another key feature is that local variables and execution states are automatically saved between calls .

In addition to automatically creating methods and saving program state , When the generator ends , They also automatically trigger  StopIteration. These characteristics combine , Make it as easy to create iterators as to write regular functions .

9.8.2 Generator Expressions

some Simple generator Can be written as simple expression code , The syntax used is similar to List derivation , But the outer layer is parentheses Not square brackets . This expression is designed for situations where the generator will be used immediately by the outer function . Generator expressions are more compact but less flexible than full generators , Compared with the equivalent list derivation, it is more Save memory .

Example :

>>> sum(i*i for i in range(10)) # sum of squares
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260
>>> unique_words = set(word for line in page for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']

9.8.3 yield As a collaborative process

yield Another niche usage scenario , It is the effect of realizing the coordination process in disguise , That is, in the same thread , Implement alternate execution of different tasks :

def mytask1():
print('task1 Start execution ')
'''
task code
'''
yield
def mytask2():
print('task2 Start execution ')
'''
task code
'''
yield
gene1=mytask1()
gene2=mytask2()
# Realization mytask1 mytask2 Alternate execution
for i in range(100):
next(gene1)
next(gene2)

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved