One 、 Class constraints
Two 、 The definition of a class
2.1、 create
2.1.1、 Class import
2.1.2、 Constructors
2.1.3、 Class properties
3、 ... and 、 Class inheritance
3.1、 Single inheritance
3.2、 Multiple inheritance
3.3、 Call the superclass method
3.4、 Property extension
3.4.1、 Fully extended
3.4.2、 Expand alone
Four 、 Class
5、 ... and 、 abstract class
5.1、 Mandatory type checking
6、 ... and 、 Class comparison
One 、 Class constraints# _ start : Private variables ;# __ Ask : Private variables , uninheritable ;# __xxx__: Can be accessed , uninheritable ;class A:def __init__(self):self._internal = 0 # Private variables cannot be accessed self.public = 1 # Accessible def public_method(self):passdef _private_method(self): # Private methods cannot be accessed passclass B:def __init__(self):self.__private = 0 # This property will be renamed in memory as _B__privatedef __private_method(self): # Can't be visited , uninheritable passdef __private_method__(self): # Can be accessed , uninheritable pass
Two 、 The definition of a class 2.1、 create class Dog:a = "0"; # amount to public static Variable , Overall """__init__ Is a default method , And self Is the default , use self The decorated attribute is public Class variables of type """def __init__(self, name, age):self.name = nameself.age = ageself.sex = "1";# Set property defaults def sit(self):print(self.name + "is now sitting" + "and sex is " + self.sex + Dog.a)@classmethoddef user_name(cls, name): # Note the use of this annotation return cls()dog = Dog("kk", 12);dog.sit()
2.1.1、 Class import stay python Divided into files 、 modular 、 class , The file and module are equivalent ; So there are several ways to import , such as dog.py Two... Are defined in the file Class, There are several import methods in the using class :
from car import Dog;# Import a specific class in a module , When it is used, it is directly Car();
import car;# Import all classes in a module , When using, you need car.Car();
from car import *;# Not recommended , Easy to cause naming conflicts
from collections import OrderedDict; # Use standard class libraries t = OrderedDict();
2.1.2、 Constructors class Date:# Primary constructordef __init__(self, year, month, day):self.year = yearself.month = monthself.day = day# Alternate [email protected] today(cls):t = time.localtime() # It receives a class As the first parameter , It is used to create and return the final instance , This cls==__init__return cls(t.tm_year, t.tm_mon, t.tm_mday)a = Date(2020, 5, 10) # Primaryb = Date.today() # Alternate
Reduce the number of arguments to the constructor :
class Structure1:# Class variable that specifies expected fields_field_list = []def __init__(self, *args):if len(args) != len(self._field_list):raise TypeError(f'Expected {len(self._field_list)} arguments')# Set the argumentsfor name, value in zip(self._field_list, args):setattr(self, name, value)# Example class definitionsclass Course(Structure1):# This line is just for an admission judgment , Not much practical , Or a statement _field_list = ['course_name', 'total_class', 'score']c = Course('python', 30, 0.3);
Key parameters
class Structure2:_field_list = []def __init__(self, *args, **kwargs):if len(args) > len(self._field_list):raise TypeError(f'Expected {len(self._field_list)} arguments')# Set all of the positional argumentsfor name, value in zip(self._field_list, args):setattr(self, name, value)# Set the remaining keyword arguments# It's through pop This way to check , If... Within the length range pop Throw an exception if something goes wrong for name in self._field_list[len(args):]:setattr(self, name, kwargs.pop(name))# Check for any remaining unknown argumentsif kwargs:raise TypeError(f"Invalid argument(s): {','.join(kwargs)}")# Example useclass Course(Structure2):_field_list = ['course_name', 'total_class', 'score']course_1 = Course('python', 30, 0.3)course_2 = Course('python', 30, score=0.3)course_3 = Course('python', total_class=30, score=0.3)
Extended keyword parameters :
class Structure3:# Class variable that specifies expected fields_field_list = []def __init__(self, *args, **kwargs):if len(args) != len(self._field_list):raise TypeError(f'Expected {len(self._field_list)} arguments')# Set the argumentsfor name, value in zip(self._field_list, args):setattr(self, name, value)# Set the additional arguments (if any)extra_args = kwargs.keys() - self._field_listfor name in extra_args:setattr(self, name, kwargs.pop(name))if kwargs:raise TypeError(f"Duplicate values for {','.join(kwargs)}")# Example useif __name__ == '__main__':class Course(Structure3):_field_list = ['course_name', 'total_class', 'score']course_1 = Course('python', 30, 0.3)course_2 = Course('python', 30, 0.3, date='8/5/2020')
2.1.3、 Class properties To create a new instance property , Its functions can be defined in the form of descriptors , A descriptor is an implementation 3 A class of core attribute access operations , They correspond to each other get\set\delete These three special methods .
# Descriptor attribute for an integer type-checked attributeclass Integer:def __init__(self, name):self.name = name""" The following three methods are just a more rigorous definition , No need , To use the descriptor above , You need to put the descriptor into a class in , So all access to the descriptor will be get/set/delete Captured """def __get__(self, instance, cls):if not instance:return selfelse:return instance.__dict__[self.name]def __set__(self, instance, value):if not isinstance(value, int):raise TypeError('Expected an int object')instance.__dict__[self.name] = valuedef __delete__(self, instance):del instance.__dict__[self.name]
Example 1:
class Point:""" Instance variables , And the following x,y It's not the same thing """x = Integer('x')y = Integer('y')def __init__(self, x, y):self.x = xself.y = yprint(Point.x.name) # xpoint = Point(3, 5)print(f'point x = {point.x}') #3print(f'point y = {point.y}') #5point.y = 6print(f'after change,point y = {point.y}') #6
3、 ... and 、 Class inheritance ptyhon When implementing inheritance, we will use a name called MRO List algorithm implementation , It has three rules :1、 The subclass will precede the parent ;2、 Multiple parent classes are checked according to their order in the list ;3、 If you have two legitimate choices for the next class , Returns the first legal parent class ;
3.1、 Single inheritanceclass A:def __init__(self):self.x = 0class B(A):def __init__(self):super().__init__() # This line needs attention , Or not , But the parent class will not be called if it is not written init Method self.y = 1
3.2、 Multiple inheritance class Base:def __init__(self):print('call Base.__init__')class A(Base):def __init__(self):Base.__init__(self)print('call A.__init__')class B(Base):def __init__(self):Base.__init__(self)print('call B.__init__')""" Implementation of multiple inheritance """class C(A,B):def __init__(self):A.__init__(self)B.__init__(self)print('call C.__init__')c = C()# call Base.__init__# call A.__init__# call Base.__init__# call B.__init__# call C.__init__
3.3、 Call the superclass method class Proxy:def __init__(self, obj):self._obj = objdef __getattr__(self, name):return getattr(self._obj, name)def __setattr__(self, name, value):if name.startswith('_'):""" Call the superclass method """super().__setattr__(name, value)else:setattr(self._obj, name, value)proxy = Proxy({})proxy.__setattr__("_name", "hm")
3.4、 Property extension 3.4.1、 Fully extended # Parent class class Person:def __init__(self, name):self.name = name# defined Getter function, auto to call the sign name.setter when it be [email protected] name(self):return self._name# defined Setter [email protected] name(self, value):if not isinstance(value, str):raise TypeError('Expected a string')self._name = value# defined Deleter [email protected] name(self):raise AttributeError("Can't delete attribute")""" Subclass """class SubPerson(Person):@propertydef name(self):print('Getting name')return super()[email protected] name(self, value):print(f'Setting name to {value}')super(SubPerson, SubPerson).name.__set__(self, value)@name.deleterdef name(self):print('Deleting name')super(SubPerson, SubPerson).name.__delete__(self)""" test """sub_person = SubPerson('Guido')print(f'name is: {sub_person.name}')
3.4.2、 Expand alone class SubPerson(Person):@Person.name.getterdef name(self):print('Getting name')return super().name # or super(SubPerson, SubPerson).name.__set__(self, value)sub_p = SubPerson('Bill')
# Out-of-service property The reason is that ,property It's actually get、set、del The set of functions , Each has its own use . The following is the correct extension method , So the following code doesn't work class SubPerson(Person):@property # Doesn't workdef name(self):print('Getting name')return super().name# If you want to use property Property is implemented with the following code class SubPerson(Person):@propertydef name(self):print('Getting name')return super()[email protected] name(self, value):print(f'Setting name to {value}')super(SubPerson, SubPerson).name.__set__(self, value)@name.deleterdef name(self):print('Deleting name')super(SubPerson, SubPerson).name.__delete__(self)
Four 、 Class import timeclass Date:# Primary constructordef __init__(self, year, month, day):self.year = yearself.month = monthself.day = day# Alternate [email protected] today(cls):t = time.localtime() # It receives a class As the first parameter , It is used to create and return the final instance , This cls==__init__return cls(t.tm_year, t.tm_mon, t.tm_mday)
""" Normal call """c = Date(2010, 12, 12)""" Class methods are used in inheritance """class NewDate(Date):passc = Date.today() # Creates an instance of Date (cls=Date)d = NewDate.today() # Creates an instance of NewDate (cls=NewDate)
5、 ... and 、 abstract class from abc import ABCMeta, abstractmethodclass IStream(metaclass=ABCMeta):@abstractmethoddef read(self, max_bytes=-1):[email protected] write(self, data):pass""" Can't be instantiated """#a = IStream()class SocketStream(IStream):def read(self, max_bytes=-1):passdef write(self, data):pass""" Check """def serialize(obj, stream):if not isinstance(stream, IStream):raise TypeError('Expected an IStream')pass
5.1、 Mandatory type checking from abc import ABCMeta, abstractmethodclass IStream(metaclass=ABCMeta):@abstractmethoddef read(self, max_bytes=-1):[email protected] write(self, data):passimport io# Register the built-in I/O classes as supporting our interfaceIStream.register(io.IOBase)# Open a normal file and type checkf = None #open('test.txt')print(f'f object is IStream type: {isinstance(f, IStream)}')#f object is IStream type: False
6、 ... and 、 Class comparison from functools import total_orderingclass Room:def __init__(self, name, length, width):self.name = nameself.length = lengthself.width = widthself.square_feet = self.length * [email protected]_orderingclass House:def __init__(self, name, style):self.name = nameself.style = styleself.rooms = list()@propertydef living_space_footage(self):return sum(r.square_feet for r in self.rooms)def add_room(self, room):self.rooms.append(room)def __str__(self):return f'{self.name}: {self.living_space_footage} square foot {self.style}'def __eq__(self, other):return self.living_space_footage == other.living_space_footagedef __lt__(self, other):return self.living_space_footage < other.living_space_footage# Build a few houses, and add rooms to themh1 = House('h1', 'Cape')h1.add_room(Room('Master Bedroom', 14, 21))h1.add_room(Room('Living Room', 18, 20))h1.add_room(Room('Kitchen', 12, 16))h1.add_room(Room('Office', 12, 12))h2 = House('h2', 'Ranch')h2.add_room(Room('Master Bedroom', 14, 21))h2.add_room(Room('Living Room', 18, 20))h2.add_room(Room('Kitchen', 12, 16))h3 = House('h3', 'Split')h3.add_room(Room('Master Bedroom', 14, 21))h3.add_room(Room('Living Room', 18, 20))h3.add_room(Room('Office', 12, 16))h3.add_room(Room('Kitchen', 15, 17))houses = [h1, h2, h3]print(f'Is {h1} bigger than {h2}: {h1 > h2}')print(f'Is {h2} smaller than {h3}: {h2 < h3}')print(f'Is {h2} greater than or equal to {h1}: {h2 >= h1}')print(f'Which one is biggest in houses: {max(houses)}')print(f'Which is smallest in houses: {min(houses)}')""""""# Is h1: 990 square foot Cape bigger than h2: 846 square foot Ranch: True# Is h2: 846 square foot Ranch smaller than h3: 1101 square foot Split: True# Is h2: 846 square foot Ranch greater than or equal to h1: 990 square foot Cape: False# Which one is biggest in houses: h3: 1101 square foot Split# Which is smallest in houses: h2: 846 square foot Ranch# """"""class House:def __eq__(self, other):passdef __lt__(self, other):pass# Methods created by @total_ordering__le__ = lambda self, other: self < other or self == other__gt__ = lambda self, other: not (self < other or self == other)__ge__ = lambda self, other: not (self < other)__ne__ = lambda self, other: not self == other
This is about Python This is the end of the article on the skills of defining inheritance and calling comparison methods of classes , More about Python Please search the previous articles of SDN or continue to browse the related articles below. I hope you will support SDN more in the future !