目录
  • 一、类的约束
  • 二、类的定义
    • 2.1、创建创建
      • 2.1.1、类的导入
      • 2.1.2、构造器
      • 2.1.3、类属性
  • 三、类的继承
    • 3.1、单继承
      • 3.2、多继承
        • 3.3、调用父类方法
          • 3.4、属性扩展
            • 3.4.1、完全扩展
            • 3.4.2、单独扩展
        • 四、类的调用
          • 五、抽象类
            • 5.1、强制类型检查
            • 六、类的比较

              一、类的约束

              # _开头: 私有变量;
              # __开问: 私有变量,不能被继承;
              # __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
              声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。