Analysis of the operating principles of various methods in Python

Source: Internet
Author: User

Analysis of the operating principles of various methods in Python

This article mainly introduces the operating principles of various methods in Python, including the similarities and differences between abstract methods and static methods and class methods. For more information, see

 

 

How does the method work in Python?

A method is a function that exists as a class attribute. You can declare and access a function in the following way:

?

1

2

3

4

5

6

7

8

>>> Class Pizza (object ):

... Def _ init _ (self, size ):

... Self. size = size

... Def get_size (self ):

... Return self. size

...

>>> Pizza. get_size

<Unbound method Pizza. get_size>

Python tells you that the attribute _ get_size is an unbound method of the Pizza class. What does this mean? Soon we will know the answer:

?

1

2

3

4

>>> Pizza. get_size ()

Traceback (most recent call last ):

File "<stdin>", line 1, in <module>

TypeError: unbound method get_size () must be called with Pizza instance as first argument (got nothing instead)

We cannot call this method because it has not been bound to any instance of the Pizza class. It requires an instance to be passed as the first parameter (Python2 must be an instance of this class, python3 can be anything), try:

?

1

>>> Pizza. get_size (Pizza (42 ))

It's great that an instance is called as its first parameter, and the whole world is quiet. If I say this call method is not the most convenient, you will also think so; yes, now we have to reference this class every time we call this method. If you don't know which class is our object, in the long run, this method does not work.

So what does Python do for us? It binds all methods from class _ Pizza and the methods of any instance of this class. This means that the current property get_size is the binding method of an instance object in Pizza. The first parameter of this method is the instance itself.

?

1

2

3

4

>>> Pizza (42). get_size

<Bound method Pizza. get_size of <__ main _. Pizza object at 0x7f3138827910>

>>> Pizza (42). get_size ()

42

As we expected, no parameters need to be provided to _ get_size because it is bound and Its self parameter is automatically set to the Pizza instance, the following code is the best proof:

?

1

2

3

>>> M = Pizza (42). get_size

>>> M ()

42

What's more, you don't need to use references that hold the Pizza object. Because this method has been bound to this object, this method is sufficient for itself.

Maybe, if you want to know which object the binding method is bound to, you can find out the following method:

?

1

2

3

4

5

6

7

8

>>> M = Pizza (42). get_size

>>> M. _ self __

<__ Main _. Pizza object at 0x7f3138827910>

>>>

# You coshould guess, look at this:

...

>>> M = m. _ self _. get_size

True

Obviously, this object still has a reference, and you can retrieve it as long as you want.

In Python3, a function attached to a class is no longer considered an unbound method, but a simple function. If necessary, it is bound to an object, the principle is still consistent with Python2, but the module is more concise:

?

1

2

3

4

5

6

7

8

>>> Class Pizza (object ):

... Def _ init _ (self, size ):

... Self. size = size

... Def get_size (self ):

... Return self. size

...

>>> Pizza. get_size

<Function Pizza. get_size at 0x7f307f984dd0>

Static Method

Static methods are a special type of methods. Sometimes you may need to write a method that belongs to this class, but these code will not use the instance object itself, for example:

?

1

2

3

4

5

6

7

Class Pizza (object ):

@ Staticmethod

Def mix_ingredients (x, y ):

Return x + y

 

Def cook (self ):

Return self. mix_ingredients (self. cheese, self. vegetables)

In this example, if _ mix_ingredients can be run as a non-static method, but it must provide the self parameter, which is not used in the method at all. Here the @ staticmethod modifier can bring us some benefits:

Python no longer needs to initialize a binding method for the Pizza object instance. The binding method is also an object, but creation costs are required, and static methods can avoid this.

?

1

2

3

4

5

6

>>> Pizza (). cook is Pizza (). cook

False

>>> Pizza (). mix_ingredients is Pizza. mix_ingredients

True

>>> Pizza (). mix_ingredients is Pizza (). mix_ingredients

True

Code with better readability. We can see that @ staticmethod does not need to depend on the state of the object.
It can be overwritten in the subclass. If mix_ingredients is used as the top-level function of the module, the subclass inherited from Pizza cannot change the mix_ingredients of pizza if it does not overwrite cook.

Class Method

Even so, what is a class method? A class method is a method bound to a class instead of an object.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

>>> Class Pizza (object ):

... Radius = 42

... @ Classmethod

... Def get_radius (cls ):

... Return cls. radius

...

>>>

>>> Pizza. get_radius

<Bound method type. get_radius of <class '_ main _. pizza'>

>>> Pizza (). get_radius

<Bound method type. get_radius of <class '_ main _. pizza'>

>>> Pizza. get_radius is Pizza (). get_radius

True

>>> Pizza. get_radius ()

42

No matter which method you use to access this method, it is always bound to this class. Its first parameter is the class itself (remember: the class is also an object ).

When will this method be used? Class methods are usually useful in the following two scenarios:

Factory method: it is used to create class instances, such as some preprocessing. If @ staticmethod is used instead, we have to hard encode the Pizza class name in the function, which makes it impossible for any class that inherits Pizza to use our factory method for its own use.

?

1

2

3

4

5

6

7

Class Pizza (object ):

Def _ init _ (self, ingredients ):

Self. ingredients = ingredients

 

@ Classmethod

Def from_fridge (cls, fridge ):

Return cls (fridge. get_cheese () + fridge. get_vegetables ())

Call static classes: if you split a static method into multiple static methods, you still need to hardcode the class name unless you use the class method. Using this method to declare a method, the Pizza class name will never be directly referenced. Inheritance and method coverage can work perfectly.

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Class Pizza (object ):

Def _ init _ (self, radius, height ):

Self. radius = radius

Self. height = height

 

@ Staticmethod

Def compute_area (radius ):

Return math. pi * (radius ** 2)

 

@ Classmethod

Def compute_volume (cls, height, radius ):

Return height * cls. compute_area (radius)

 

Def get_volume (self ):

Return self. compute_volume (self. height, self. radius)

Abstract Method

Abstract methods are defined in a base class. They do not provide any implementation, similar to the methods in interfaces in Java.

The simplest way to implement abstract methods in Python is:

?

1

2

3

Class Pizza (object ):

Def get_radius (self ):

Raise NotImplementedError

Any class inherited from _ Pizza must overwrite the implementation method get_radius. Otherwise, an exception is thrown.

The implementation of this abstract method has its drawbacks. if you write a class that inherits Pizza but forget to implement get_radius, the exception will only be thrown out when you are actually using it.

?

1

2

3

4

5

6

7

>>> Pizza ()

<__ Main _. Pizza object at 0x7fb7471_d90>

>>> Pizza (). get_radius ()

Traceback (most recent call last ):

File "<stdin>", line 1, in <module>

File "<stdin>", line 3, in get_radius

NotImplementedError

Another way is to trigger an error earlier. You can use the abc module provided by Python to throw an exception after the object is initialized:

?

1

2

3

4

5

6

7

8

9

Import abc

 

Class BasePizza (object ):

_ Metaclass _ = abc. ABCMeta

 

@ Abc. abstractmethod

Def get_radius (self ):

 

"Method that shoshould do something ."""

After abc is used, you will immediately get a TypeError when you try to initialize BasePizza or any subclass, instead of waiting until the get_radius is called.

?

1

2

3

4

>>> BasePizza ()

Traceback (most recent call last ):

File "<stdin>", line 1, in <module>

TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius

Hybrid static methods, class methods, and abstract methods

It's time for you to mix these decorators when building classes and inheritance structures, so here are some tips.

Remember, declaring an abstract method won't fix the prototype of the method, which means that although you must implement it, I can implement it using any parameter list:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Import abc

 

Class BasePizza (object ):

_ Metaclass _ = abc. ABCMeta

 

@ Abc. abstractmethod

Def get_ingredients (self ):

 

"Returns the ingredient list ."""

 

Class Calzone (BasePizza ):

Def get_ingredients (self, with_egg = False ):

Egg = Egg () if with_egg else None

Return self. ingredients + egg

This is acceptable because Calzone meets the interface requirements defined by the BasePizza object. We can also use a class method or static method to achieve this:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

Import abc

 

Class BasePizza (object ):

_ Metaclass _ = abc. ABCMeta

 

@ Abc. abstractmethod

Def get_ingredients (self ):

 

"Returns the ingredient list ."""

 

Class DietPizza (BasePizza ):

@ Staticmethod

Def get_ingredients ():

Return None

This is also true because it follows the contract set by the abstract class BasePizza. In fact, the get_ingredients method does not need to know what the returned results are. The results are implementation details, not contractual conditions.

Therefore, you cannot force the implementation of abstract methods to be a conventional method, a class method, or a static method. There is nothing to argue about. Starting from Python3 (you cannot run as expected in Python2, see issue5867), it is possible to use @ staticmethod and @ classmethod decorator on the abstractmethod method.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

Import abc

 

Class BasePizza (object ):

_ Metaclass _ = abc. ABCMeta

 

Ingredient = ['chees']

 

@ Classmethod

@ Abc. abstractmethod

Def get_ingredients (cls ):

 

"Returns the ingredient list ."""

Return cls. ingredients

Don't get it wrong. If you think it will force the subclass as a class method to implement get_ingredients, you will be wrong. It only indicates that the get_ingredients you implement is a class method in BasePizza.

Can code be implemented in abstract methods? That's right. Python is the opposite of a method in the Java interface. You can write the implementation code in the abstract method and call it through super. In Java 8, the interface also provides the default method, allowing you to write the implementation of the method in the interface)

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Import abc

 

Class BasePizza (object ):

_ Metaclass _ = abc. ABCMeta

 

Default_ingredients = ['chees']

 

@ Classmethod

@ Abc. abstractmethod

Def get_ingredients (cls ):

 

"Returns the ingredient list ."""

Return cls. default_ingredients

 

Class DietPizza (BasePizza ):

Def get_ingredients (self ):

Return ['egg'] + super (DietPizza, self). get_ingredients ()

In this example, each pizza you construct inherits the BasePizza method. You have to override the get_ingredients method, but you can use the default mechanism to obtain the ingredient list through super.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.