目录
一、类的约束
# _开头: 私有变量; # __开问: 私有变量,不能被继承; # __xxx__: 能被访问,不能被继承; class A: def __init__(self): self._internal = 0 # 私有变量不能被访问 self.public = 1 # 可被访问 def public_method(self): pass def _private_method(self): # 私有方法不能被访问 pass class B: def __init__(self): self.__private = 0 # 这个属性会在内存中被重新命名为_B__private def __private_method(self): # 不能被访问,不能被继承 pass def __private_method__(self): # 能被访问,不能被继承 pass
二、类的定义
2.1、创建创建
class Dog: a = \"0\"; #相当于public static变量,全局的 \"\"\"__init__是一个默认的方法,且self为默认的,用self修饰的属性为public类型的类变量\"\"\" def __init__(self, name, age): self.name = name self.age = age self.sex = \"1\";#设置属性默认值 def sit(self): print(self.name + \"is now sitting\" + \"and sex is \" + self.sex + Dog.a) @classmethod def user_name(cls, name): #注意这种注解的用法 return cls() dog = Dog(\"kk\", 12); dog.sit()
2.1.1、类的导入
在python中分为文件、模块、类,其中文件和模块可划等价;所以导入有几种方式,比如dog.py文件中定义了两个Class,则在使用类中导入方法有以下几种:
- from car import Dog;#导入一个模块中的特定类,使用时则直接Car();
- import car;#导入一个模块中的所有类,使用时则需要car.Car();
- from car import *;#不推荐,容易引起命名冲突问题
from collections import OrderedDict; #使用标准类库 t = OrderedDict();
2.1.2、构造器
class Date: # Primary constructor def __init__(self, year, month, day): self.year = year self.month = month self.day = day # Alternate constructor @classmethod def today(cls): t = time.localtime() #它接收一个class作为第一个参数,它被用来创建并返回最终的实例, 这个cls==__init__ return cls(t.tm_year, t.tm_mon, t.tm_mday) a = Date(2020, 5, 10) # Primary b = Date.today() # Alternate
减少构造函数的参数个数:
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 arguments for name, value in zip(self._field_list, args): setattr(self, name, value) # Example class definitions class Course(Structure1): # 这行只是为了一个准许入判断,没有太多实际意思,或是一个声明 _field_list = [\'course_name\', \'total_class\', \'score\'] c = Course(\'python\', 30, 0.3);
关键字参数
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 arguments for name, value in zip(self._field_list, args): setattr(self, name, value) # Set the remaining keyword arguments #是通过pop这种方式来检查的,在长度范围内如果pop出错则抛异常 for name in self._field_list[len(args):]: setattr(self, name, kwargs.pop(name)) # Check for any remaining unknown arguments if kwargs: raise TypeError(f\"Invalid argument(s): {\',\'.join(kwargs)}\") # Example use class 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)
扩展关键字参数:
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 arguments for name, value in zip(self._field_list, args): setattr(self, name, value) # Set the additional arguments (if any) extra_args = kwargs.keys() - self._field_list for name in extra_args: setattr(self, name, kwargs.pop(name)) if kwargs: raise TypeError(f\"Duplicate values for {\',\'.join(kwargs)}\") # Example use if __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、类属性
要创建一个新的实例属性,可以通过描述器的形式来定义它的功能,一个描述器就是一个实现了3个核心属性访问操作的类,分别对应get\\set\\delete这三个特殊的方法。
# Descriptor attribute for an integer type-checked attribute class Integer: def __init__(self, name): self.name = name \"\"\"下面三个方法只是一个更严格的定义,可以不需要,要使用上面的描述器,需要把描述器放入到一个class中,这样所有对描述器的访问都会被get/set/delete所捕获\"\"\" def __get__(self, instance, cls): if not instance: return self else: 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] = value def __delete__(self, instance): del instance.__dict__[self.name]
示例1:
class Point: \"\"\"实例变量,和下面的x,y不是一回事\"\"\" x = Integer(\'x\') y = Integer(\'y\') def __init__(self, x, y): self.x = x self.y = y print(Point.x.name) # x point = Point(3, 5) print(f\'point x = {point.x}\') #3 print(f\'point y = {point.y}\') #5 point.y = 6 print(f\'after change,point y = {point.y}\') #6
三、类的继承
ptyhon在实现继承时会用一个叫MRO列表的算法实现,它有三条规则:1、子类会先于父类;2、多个父类会根据它们在列表中的顺序被检查;3、如果对下一个类有两个合法的选择,则返回第一个合法的父类;
3.1、单继承
class A: def __init__(self): self.x = 0 class B(A): def __init__(self): super().__init__() #这行需要注意,也可以不写,但不写时就不会调用父类的init方法 self.y = 1
3.2、多继承
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__\') \"\"\"多继承的实现\"\"\" 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、调用父类方法
class Proxy: def __init__(self, obj): self._obj = obj def __getattr__(self, name): return getattr(self._obj, name) def __setattr__(self, name, value): if name.startswith(\'_\'): \"\"\"调用父类方法\"\"\" super().__setattr__(name, value) else: setattr(self._obj, name, value) proxy = Proxy({}) proxy.__setattr__(\"_name\", \"hm\")
3.4、属性扩展
3.4.1、完全扩展
# 父类 class Person: def __init__(self, name): self.name = name # defined Getter function, auto to call the sign name.setter when it be build @property def name(self): return self._name # defined Setter function @name.setter def name(self, value): if not isinstance(value, str): raise TypeError(\'Expected a string\') self._name = value # defined Deleter function @name.deleter def name(self): raise AttributeError(\"Can\'t delete attribute\") \"\"\"子类\"\"\" class SubPerson(Person): @property def name(self): print(\'Getting name\') return super().name @name.setter def name(self, value): print(f\'Setting name to {value}\') super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print(\'Deleting name\') super(SubPerson, SubPerson).name.__delete__(self) \"\"\"测试\"\"\" sub_person = SubPerson(\'Guido\') print(f\'name is: {sub_person.name}\')
3.4.2、单独扩展
class SubPerson(Person): @Person.name.getter def name(self): print(\'Getting name\') return super().name # or super(SubPerson, SubPerson).name.__set__(self, value) sub_p = SubPerson(\'Bill\')
#不能用property的原因是,property其实是get、set、del函数的集合,各有各的用处。下面才是正确的扩展方式,所以下面的代码是不工作的 class SubPerson(Person): @property # Doesn\'t work def name(self): print(\'Getting name\') return super().name #如果要用property属性则要用下面的编码实现 class SubPerson(Person): @property def name(self): print(\'Getting name\') return super().name @name.setter def name(self, value): print(f\'Setting name to {value}\') super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print(\'Deleting name\') super(SubPerson, SubPerson).name.__delete__(self)
四、类的调用
import time class Date: # Primary constructor def __init__(self, year, month, day): self.year = year self.month = month self.day = day # Alternate constructor @classmethod def today(cls): t = time.localtime() #它接收一个class作为第一个参数,它被用来创建并返回最终的实例, 这个cls==__init__ return cls(t.tm_year, t.tm_mon, t.tm_mday)
\"\"\"普通调用\"\"\" c = Date(2010, 12, 12) \"\"\"类方法在继承中使用\"\"\" class NewDate(Date): pass c = Date.today() # Creates an instance of Date (cls=Date) d = NewDate.today() # Creates an instance of NewDate (cls=NewDate)
五、抽象类
from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, max_bytes=-1): pass @abstractmethod def write(self, data): pass \"\"\"不能被实例化\"\"\" #a = IStream() class SocketStream(IStream): def read(self, max_bytes=-1): pass def write(self, data): pass \"\"\"检查\"\"\" def serialize(obj, stream): if not isinstance(stream, IStream): raise TypeError(\'Expected an IStream\') pass
5.1、强制类型检查
from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, max_bytes=-1): pass @abstractmethod def write(self, data): pass import io # Register the built-in I/O classes as supporting our interface IStream.register(io.IOBase) # Open a normal file and type check f = None #open(\'test.txt\') print(f\'f object is IStream type: {isinstance(f, IStream)}\') #f object is IStream type: False
六、类的比较
from functools import total_ordering class Room: def __init__(self, name, length, width): self.name = name self.length = length self.width = width self.square_feet = self.length * self.width @total_ordering class House: def __init__(self, name, style): self.name = name self.style = style self.rooms = list() @property def 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_footage def __lt__(self, other): return self.living_space_footage < other.living_space_footage # Build a few houses, and add rooms to them h1 = 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): pass def __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
© 版权声明
THE END
暂无评论内容