Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to make a comprehensive analysis of classes in python

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article shows you how to carry out a comprehensive analysis of the classes in python, the content is concise and easy to understand, it will definitely brighten your eyes. I hope you can get something through the detailed introduction of this article.

The important concepts of object-oriented are Class and Instance. A class is an abstract template, while an instance is a concrete "object" created according to the class. Each object has the same method, but its data may be different.

Let's first review the common terms of OOP:

Class: a description or definition of a set of objects with the same data and methods.

Object: an object is an instance of a class.

Instance: an instantiated implementation of an object.

Instance properties (instance attribute): an object is a collection of properties.

Instance method (instance method): a collection of functions that access or update one or more properties of an instance of an object.

Class classattribute: properties that belong to all objects in a class and do not change only on an instance

Class methods (classmethod): functions that are subordinate to the class that work without a specific object instance.

Class Overview

In Python, a class is defined by the class keyword:

Class Student (object): pass

Class is followed by the class name, or Student, which is usually a word that begins with an uppercase, followed by (object), indicating which class the class inherited.

> bart = Student () > bart > Student

As you can see, the variable bart points to an object of Student, followed by a memory address, each object has a different address, and Student itself is a class.

> bart.name = 'Bart Simpson' > bart.name' Bart Simpson'

Because a class can act as a template, you can force some properties that we think must be bound into it when creating an instance. By defining a special init method, attributes such as name,score are tied when the instance is created.

Class Student (object): def _ _ init__ (self, name, score): self.name = name self.score = score

Notice that the * parameters of the init method are always self, indicating the created instance itself, so inside the init method, you can bind various properties to the self, because self points to the created instance itself.

With the init method, you cannot pass an empty parameter when creating an instance. You must pass a parameter that matches the init method, but self does not need to pass it. The Python interpreter will pass in the instance variable itself:

> bart = Student ('Bart Simpson', 59) > bart.name' Bart Simpson' > bart.score 59

Compared with ordinary functions, the object functions defined in the class (and static methods, class methods) are only different in that the * arguments are always instance variables self, and you don't have to pass this parameter when called.

New class, old class

The new class of python was introduced in version 2.2, and the previous class was called the classical class or the old class. In Python 2.x, if a class inherits from a base class (which can be a custom class or another class) or inherits from object, it is a new class; a class that does not inherit is a classical class. Python 3.x are all new classes.

The new class is endowed with many new features (such as unifying types and classes) and changing some contents of the previous classical class (such as changing the execution order of methods under multi-inheritance).

For unified classes (class) and types (type), see the following example

Class OldClass (): pass o = OldClass () print o.classrooms classrooms _ # _ main__.OldClass print type (o) # class newClass (object): pass n = newClass () print n.classrooms classrooms _ # print type (n) #

Object attribute

The properties of an object in Python contain all the contents of the object: methods and data. Note that methods are also properties of the object. When looking for the attributes of an object, first look in the _ _ dict__ of the object, then the dict of the class to which the object belongs, and then the dict of the parent class (MRO parsing) in the inheritance system. The search is terminated if found anywhere, and the attribute value is obtained by calling the _ _ getattribute__ (or _ _ getattr__) method.

Method

There are three methods in the Python class, namely, static method (staticmethod), class method (classmethod), and instance method:

For instance methods, each time you define an instance method in a class, you need to specify an instance (the method has * parameters, and the name is customarily self). Assuming that object a has an instance method foo (self, * args, * * kwargs), you can use a.foo (* args, * * kwargs) or A.foo (a, * args, * * kwargs) when calling, which is exactly the same to the interpreter.

Each time a class method is defined, you need to specify a class (the method has * parameters, and the name convention is cls). Similar to the instance method, you need to specify a class when calling.

Static methods are actually the same as ordinary methods, except that you need to use a class or instance when calling. Static methods are needed because sometimes you need to put a set of logically related functions in a class to facilitate the organization of the code structure. In general, if a method does not need to use self, then it is suitable for use as a static method.

Specific examples are as follows:

Def foo (x): print "executing foo (% s)"% (x) class A (object): def foo (self): print "executing foo (% s)"% self @ classmethod def class_foo (cls): print "executing class_foo (% s)"% cls @ staticmethod def static_foo (): print "executing static_foo ()" a = A () print a .foo print A.foo print a.class_foo print A.class_foo print A.static_foo print a.static_foo print foo #

There are two methods when accessing class methods, called unbound methods (unbound method) and bound methods (bound method):

Unbound method: an unbound method object is returned by referencing the instance method through the class. To call it, you must explicitly provide an instance as * parameters, such as A.foo.

Bound method: returns a bound method object through the instance access method. Python automatically binds an instance to the method, so you don't have to pass an instance parameter, such as a.foo, when calling it.

Data attribute

The following creates a class for Student and implements the initialization function "_ _ init__" for this class:

In the Student class above, count, books, name, and age are all called class data properties, but they are divided into class data properties and instance data properties. The properties defined directly in the body of the class are called class properties, while the properties defined in the methods of the class are called instance properties.

First, take a look at the following code, which shows access to class data properties and instance data properties:

Student.books.extend (["python", "javascript"]) print "Student book list:% s"% Student.books # class can add class attribute after class definition Student.hobbies = ["reading", "jogging", "swimming"] print "Student hobby list:% s" Student.hobbies print dir (Student) # class instance attribute wilber = Student ("Wilber", 28) print "% s is% d years old"% (wilber.name Wilber.age) # class instance can add new attribute # "gender" is the instance attribute only belongs to wilber wilber.gender = "male" print "s is% s"% (wilber.name, wilber.gender) # class instance can access class attribute wilber.books.append ("C #") print wilber.books

You can see what properties a class or instance has through the built-in function dir () or by accessing the dictionary attribute _ _ dict__, of the class. For class data properties and instance data properties, they can be summarized as follows:

The class data attribute belongs to the class itself and can be accessed / modified through the class name.

Class data properties can also be accessed / modified by all instances of the class

After the class definition, the class data attributes can be dynamically added through the class name, and the new class attributes are shared by the class and all instances.

Instance data properties can only be accessed through an instance

After the instance is generated, you can also add instance data properties dynamically, but these instance data properties only belong to the instance.

Take a look at the following program.

In the above program, p1.name = "bbb" is the class variable called by the instance. P1.name initially points to the class variable name= "aaa", but changes the reference to the class variable in the scope of the instance to become an instance variable. Self.name no longer refers to Person's class variable name.

Class Person: name= [] p1=Person () p2=Person () p1.name.append (1) print p1.name # [1] print p2.name # [1] print Person.name # [1]

Special class attribute

For all classes, there is a special set of properties:

Through these properties, you can get some information about the Student class, as follows:

Inheritance of class

Class DerivedClass (BaseClass1, [BaseClass2...]):.

Calls the unbound constructor of the parent class. When a method of an instance is called, the self parameter of that method is automatically bound to the instance (called a bound method). But if you call a method of the class (such as A.init) directly, then no instance will be bound. In this way, you are free to provide the required self parameters, which is called the unbound method. It works fine in most cases, but the parent class may be called repeatedly in the case of multiple inheritance.

Call the function of the next class in MRO through super (cls, inst). Method (). Here is a very good explanation, and you should be familiar with super after reading it.

The unbound (unbound) method call is as follows:

Class Base (object): def _ init__ (self): print ("Base.__init__") class Derived (Base): def _ init__ (self): Base.__init__ (self) print ("Derived.__init__")

The supper call is as follows:

Class Base (object): def _ init__ (self): print "Base.__init__" class Derived (Base): def _ init__ (self): super (Derived, self). _ _ init__ () print "Derived.__init__" class Derived_2 (Derived): def _ init__ (self): super (Derived_2) Self). _ _ init__ () print "Derived_2.__init__"

Inheritance mechanism MRO

MRO is mainly used to determine which class the invoked property comes from in the case of multiple inheritance. The previous class of Python2.2 is a classical class, it is a class without inheritance, and the instance type is type type. If the classical class is used as the parent class, the child class will make an error when calling the constructor of the parent class. At this time, the method of MRO is DFS (depth first search), and the order of child nodes is from left to right. Inspect.getmro (A) can view the MRO order of classic classes.

Advantages and disadvantages of the two inheritance modes under DFS:

*, multiple inheritance of two unrelated classes. In this case, the DFS sequence is normal and will not cause any problems.

The second is the prism inheritance mode, where there is multiple inheritance of the common parent class (D), in which case the DFS must pass through the common parent class (D). If this common parent class (D) has some initialization properties or methods, but the subclass (C) rewrites these properties or methods, then the properties or methods of D must be found first according to the DFS order, then the properties or methods of C will never be accessed, resulting in C can only inherit and cannot be rewritten (override). This is why the new classes do not use DFS because they all have a common ancestor, object.

In order to unify classes and built-in types, the Python2.2 version introduces new classes. Each class of the new class inherits from a base class, can be a custom class or other class, inherits from object by default, and the subclass can call the constructor of the parent class. You can see the order of the new classes with A. updated classes _.

In 2.2, there are two ways to MRO:

If it is a classic class, MRO is DFS

If the new class MRO is BFS (breadth-first search), the order of child nodes is from left to right.

Advantages and disadvantages of the two inheritance modes of the new class under BFS:

* species, normal inheritance mode. For example, B clearly inherits an attribute of D (assuming foo), and C also implements this attribute foo, then BFS accesses B and then C, but the foo attribute of An is c, which is called monotonicity.

Second, the prismatic inheritance mode, the search order of BFS solves the problem that only inheritance can not be rewritten in DFS order.

Because both DFS and BFS have big problems, the MRO of the new class from Python2.3 uses the C3 algorithm to solve the monotonicity problem and the problem that can only be inherited and cannot be rewritten. The sequence of C3 algorithm for MRO is shown below:

C3 uses the topological sorting algorithm of the graph, the specific implementation can refer to the official website documentation.

Polymorphisms

Polymorphism is a variety of forms, and its state is determined at run time, but its type cannot be determined at the compilation stage. Polymorphism in Python is a little different from polymorphism in Java and C++. Variables in Python are dynamically typed. You don't need to specify their type when defining them. Instead, they determine their types at run time as needed.

Python itself is an interpretive language and does not precompile, so it only determines its state at run time, so some people say that Python is a polymorphic language. The characteristics of polymorphism can be reflected in many places in Python, such as the built-in function len (object). The len function can calculate not only the length of the string, but also the number of data in lists, tuples and other objects. Here, the specific calculation process is determined by the parameter type at run time, which is a manifestation of polymorphism.

Special class method

There are often methods in a class that are named with two underscores surrounded by underscores. The following figure shows some examples. Using them properly can add some "magic" behavior to the class.

Structure and deconstruction

When we call x = SomeClass (), the * * called function is _ _ new__, which creates an instance. Next you can use _ _ init__ to indicate the initialization behavior of an object. _ _ del__ is called when the life cycle of this object ends.

_ _ new__ (cls, [...]) Is the method that is called when the object is instantiated. It only takes down the cls parameter and passes the other parameters to init.

_ _ init__ (self, [...]) Initialize the method for the class. It takes any parameters passed to the constructor (for example, if we call x = SomeClass (10, 'foo'), the init function will receive arguments 10 and' foo').

_ del__ (self): new and init are the constructors of the object, and del is the destroyer of the object. It does not implement the statement del x (so it is not the same as x.collection delaying _ ()), but rather defines the behavior when the object is reclaimed.

When we create an instance of a class, we first call new to create the instance, and then call init to initialize it. Note, however, that in the old class, the creation of the instance does not call the new method, as shown in the following example:

Class A: def _ _ new__ (cls): print "A.The latest news _ is called" #-> this is never called A ()

For new classes, we can override the new method. Note that the * parameter cls (which is actually the current class type) of the method is used to indicate the type to be created, and the subsequent parameters are passed to init for initialization. If new returns an object of type cls, then call init next, otherwise init will not be called (you must pass an instance object to call this method).

Class A (object): #-> don't forget the object specified as base def _ new__ (cls): print "A.The news news _ called" return super (A, cls). _ _ new__ (cls) def _ _ init__ (self): print "A.birthday news _ called" A ()

Here we call super () to get the new method of the next class An in MRO (in this case, the base class object) to create an instance object of cls, and then use this object to call init. In the following example, no appropriate object is returned, so init is not called:

Class Sample (object): def _ _ str__ (self): return "SAMPLE" class A (object): def _ new__ (cls): print "A. Cls). _ new__ (Sample) # return Sample () def _ _ init__ (self): print "A.The initableness _ called" #-> is actually never called a = A () # A.The newcomers _ called

Here is a very good explanation for super. To put it simply, super does the following:

Def super (cls, inst): mro = inst.__class__.mro () return mro [mro.index (cls) + 1]

About MRO, this article is very good: do you really understand the MRO algorithm in Python? to put it simply, in the C3 algorithm of the new class MRO, it is guaranteed that the base class always appears after the derived class, and if there are multiple base classes, the relative order of the base class remains the same.

Operator

Special methods can be used to build an object with Python built-in type behavior, which means that you can avoid using non-standard, ugly ways to express simple operations. In some languages, this is common:

If instance.equals (other_instance): # do something

Of course, this can be done in Python, but it makes the code lengthy and confusing. Different class libraries may use different method names for the same comparison operation, which makes users need to do a lot of unnecessary work. So we can define the method _ _ eq__, and then use it like this:

If instance = = other_instance: # do something

Python has many special functions that correspond to commonly used operators, such as:

_ _ cmp__ (self, other): defines the behavior of all comparison operators. It should be in self.

< other 时返回一个负整数,在 self == other 时返回0,在 self >

Returns a positive integer when other.

_ _ ne__ (self, other): define a behavior that is not equal to the operator (! =) (if eq is defined, you must also define ne!)

_ _ le__ (self, other): defines behaviors that are less than or equal to the operator ().

Numeric operator

It can be divided into five categories: unary operators, common arithmetic operators, reflection arithmetic operators, enhanced assignment operators, and type conversion operators. Here are some examples:

_ _ pos__ (self) implements correcting operations, such as + some_object

_ _ invert__ (self) implementation fetch inverse operator ~

_ _ add__ (self, other) to implement the addition operation

_ _ sub__ (self, other) to achieve subtraction

_ _ radd__ (self, other) to implement reflection addition

_ _ rsub__ (self, other) to implement reflection subtraction

_ _ floordiv__ (self, other) implements integer division using the / / operator

_ _ iadd__ (self, other) implements addition assignment.

_ _ isub__ (self, other) implements subtraction assignment.

_ _ int__ (self) implements type conversion to int.

_ _ long__ (self) implements type conversion to long.

Reflection operator methods do the same thing as their common versions, except that they deal with the case after swapping two operands. Type conversion operator, which is mainly used to implement built-in type conversion functions such as float ().

Representation of class

Using strings to represent classes is a quite useful feature. There are some built-in methods in Python that return the representation of the class, and there are also a series of special methods that can be used to customize the behavior of the class when using these built-in functions.

_ _ str__ (self) defines the behavior when str () is called on an instance of the class.

_ _ repr__ (self) defines the behavior when repr () is called on an instance of the class. The main difference between str () and repr () is the "target user". The purpose of repr () is to produce machine-readable output (in most cases, its output can be used as valid Python code), while str () produces human-readable output.

_ _ dir__ (self) defines the behavior when dir () is called on an instance of the class, which should return a list of properties to the caller.

Attribute control

In Python, overloading the _ _ getattr__, _ _ setattr__, _ _ delattr__, and _ _ getattribute__ methods can be used to manage property access in a custom class. Where:

The getattr method will intercept all undefined property acquires (this method will not be called when the property to be accessed has been defined, and the definition is not defined, which is determined by whether the property can be found by Python)

The getattribute method will intercept the acquisition of all properties (regardless of whether the property has been defined or not, the method will be called as long as it gets its value), so when both the getattr and getattribute methods are overloaded in a class, getattr will never be called, and the getattribute method only exists in the new classes of Python2.6 and all classes of Python3.

The setattr method will intercept all property assignments

The delattr method will intercept the removal of all properties.

In Python, properties in a class or class instance are dynamic (because Python is dynamic), that is, you can add or remove an attribute to a class or class instance.

Because the getattribute, setattr, and delattr methods intercept all properties, you can no longer code them as usual, and be careful to avoid recursive calls (which can cause an endless loop if recursion occurs); however, there are not so many restrictions on the getattr method.

The format "self.name = value" cannot be used when overloading the setattr method, otherwise it will cause recursive calls and fall into a dead loop. The correct thing should be:

Def _ setattr__ (self, name, value): # do-something object.__setattr__ (self, name, value) # do-something

The sentence of object.__setattr__ (self, name, value) can be replaced by self.__dict__ [name] = value. But the premise is that you must make sure that the getattribute method is overloaded correctly (if the getattribute method is overloaded), otherwise, it will result in an error in the assignment, because self.dict will trigger the acquisition of the dict property in all properties of the self, which will trigger a call to the getattribute method, and if the getattribute method overloads the error, the setattr method will naturally fail.

Custom sequence

There are many ways to make Python classes behave like built-in sequence types (dictionaries, tuples, lists, strings, etc.).

Implementing custom container types in Python requires some protocols. First of all, immutable container types have the following protocol: to implement an immutable container, you need to define _ _ len__ and _ _ getitem__.

Context management

The context management protocol (Context Management Protocol) contains methods _ _ enter__ () and _ _ exit__ (), which are implemented by objects that support the protocol.

Enter: enter the runtime context of the context manager. If the as clause is specified, the return value is assigned to target in the as clause.

Exit: exits the runtime context associated with the context manager. Returns a Boolean value indicating whether the exception that occurred is handled.

The enter method of the context manager is called before the block of code wrapped in the with statement is executed, and the exit method is executed after the statement body is executed.

The syntax format of the with statement is as follows:

With context_expression [as target (s)]: with-body

Python improves some built-in objects and adds support for context manager, which can be used in with statements, such as automatic closing of files, automatic acquisition and release of thread locks, and so on. Examples are as follows:

> with open ("etc/CS.json") as d:...: print d > > print d > print dir (d) ['_ _ class__','_ _ delattr__','_ _ doc__','_ enter__','_ exit__',...]

By using the with statement, you can guarantee that the open file handle has been closed after the with statement has been executed, regardless of whether an exception occurred during file processing.

The above content is how to conduct a comprehensive analysis of the classes in python. Have you learned the knowledge or skills? If you want to learn more skills or enrich your knowledge reserve, you are welcome to follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report