Python5 常用模块与面向对象

Python5 ---- 常用模块与面向对象

常用模块与面向对象

导入第三方模块

  • 导包的层级关系
    • 模块(module)
      以文件为载体, 包含各类对象
    • 包(package)
      以文件夹为载体, 包含了各类模块
    • 库(lib)
      包含了各类包
  • import 库
  • from 库/模块 import 模块/函数
  • 导包的命名冲突
    通过as这个关键词来给当前模块/函数取个别名
    from datetime import datetime as p_datetime

时间模块time

调用的都是系统级的接口, 提供时间的访问和转换的功能

  • 查看时间
    • 获取当前时间

      # 有时区的
      time.localtime()
      
      返回的是一个time.struct_time对象
    • 时间戳

      time.time()
    • 时间的格式化输出

      now = time.localtime()
      now = time.strftime("%Y-%m-%d %H:%M:%S", now)
      print(now)
      
      # 可以省略时间对象
      now = time.strftime("%Y-%m-%d %H:%M:%S")
    • 运算
      将时间对象转换为list, 对相应的时间重新赋值后, 通过time.struct_time生成一个新的时间对象

      time_list = list(time.localtime())
      time_list[2] = 4
      time.struct_time(time_list)
    • 时间休眠
      当前程序休眠n秒

      time.sleep(3)

时间模块datetime

封装了time, 提供了更高级和更友好的接口

  • 查看时间

    # 获取计算机时间, 返回的是一个datetime.datime对象.在交互式优先_repr__()接口,__str__()
    datetime.datetime.today()
    
    # 获取指定时区的时间
    datetime.datetime.now(tz=None)
    
    # 获取utc时间
    datetime.datetime.utcnow()
  • 时间格式的转换

    • datetime.datetime -> str

      now = datetime.datetime.now(tz=None)
      now.strftime("%Y-%m-%d %H:%M:%S")
    • str -> datetime.datetime

      >>> now
      '2021-01-03 23:38:26'
      >>> datetime.datetime.strptime(now, "%Y-%m-%d %H:%M:%S")
      datetime.datetime(2021, 1, 3, 23, 38, 26)
    • datetime.datetime -> timestamp

      >>> now
      datetime.datetime(2021, 1, 3, 23, 40, 45, 749240)
      >>> now.timestamp()
      1609688445.74924
    • timestamp -> datetime.datetime

      >>> ts
      1609688445.74924
      >>> datetime.datetime.fromtimestamp(ts, tz=None)
      datetime.datetime(2021, 1, 3, 23, 40, 45, 749240)
  • 时间运算

    • timedelta
      只作用于datetime.datetime格式

      # 选中目标模块  ctrl+B / command+B 跳转到模块源码     
          def __new__(cls, days=0, seconds=0, microseconds=0,
                      milliseconds=0, minutes=0, hours=0, weeks=0):
      >>> from datetime import timedelta
      >>> now + timedelta(hours=-1)
      datetime.datetime(2021, 1, 3, 22, 40, 45, 749240)

课后作业

  • 通过datetime模块完成时间戳, datetime.datetime对象, 格式化字符串三者之间的转换
import datetime

now = datetime.datetime.now()

# datetime转str
time_str = now.strftime("%Y-%m-%d %H:%M:%S")

# str转datetime
str_time = datetime.datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")

# datetime转timestamp
time_smp = now.timestamp()

# timestamp转datetime
smp_time = datetime.datetime.fromtimestamp(time_smp)
  • 封装一个函数get_date(day_delta), 如果传入的是-1 , 输出就是字符串日期2020-01-02.
import datetime
# from datetime import timedelta

def get_date(day=-1):
    if day == -1:
        now = datetime.datetime.now(tz=None)
        # td = now + timedelta(days=day)
        str_time = now.strftime('%Y-%m-%d')
        print(str_time)
    else:
        print("请输入为-1,获取当前日期")
    return


get_date()

类的创建, 实例化, 初始化

  • 什么是类
    类就是拥有相同功能或者相同属性的对象集合

  • 类的创建

    • object是所有类的基类
      class GoGamer(object):
          subject = 'go'
      
      print(GoGamer)
  • 类的实例化
    实例就是抽象概念的具象化

    kejie = GoGamer()
    print(kejie)
  • 类的初始化
    类创建一个新实例的时候会默认调用__init__这样一个特殊方法

    class GoGamer(object):
        subject = 'go'
        def __init__(self, obj):
            self.p = obj
    
    kejie = GoGamer("金勺子")
    # 等同于以下
    # kejie.__init__('金钥匙')
    print(f"柯洁含着{kejie.p}出生")
    • 关于self
      指代还未实例化的实例

面向对象

  • 面向过程

    • 程序=数据结构+算法
    • 强调的是一个实现的细节
  • 面向对象
    完成对越来越庞大项目代码以及对外公开接口的归类和重(chong)用, 是一种更高级的抽象.

    • 通过什么手段来完成上述目的?
      • 继承

        class ChineseGoGamer(GoGamer):
            nation = 'cn'
        
        class KoreaGoGamer(GoGamer):
            nation = 'kr'
        • 处理多继承冲突

          • 查看MRO(mehotd resolution order)

            class A:
                def __init__(self):
                    print("init A")
            
            class B:
                def __init__(self):
                    print("init B")
            
            class C(A, B):
                pass
            
            print(C.__mro__)
            
            默认继承第一个
          • 指定类方法的调用顺序

            class C(A, B):
                def __init__(self):
                    super(A, self).__init__()
              

          指定当前前一个类,可用mro属性查看,简单来说就是获取当前解释顺序传入当前糨的index+1,索引加1

          
          - `super`函数源码
            def super(cls, inst):
          	mro = inst.__class__.mro()
          	return mro[mro.index(cls) + 1]
          
            def super(类, 实例):
          	# 获取当前实例的方法解析顺序
          	mro = 实例.类.mro()
          	return mro[mro.index(类) + 1]
      • 多态
        方式为覆盖和重载

        • 覆盖(子类和父类之间的, 是垂直的关系)
          子类可以继承父类的所有属性和方法, 但是同时子类也可以重写父类的属性和方法, 达到自定义的目的.

          class A:
              def __init__(self):
                  print("init A")
          
          class B:
              def __init__(self):
                  print("init B")
          
          class C(A, B):
              def __init__(self):
                  print("init C")
          		
          #class D:
          #	def a(self, a):
          #		return a
          #	def a(self, a, b):
          #		return a ** b
        • 重载(类中的方法和方法之间的, 是水平关系)
          Python中式没有重载, 但是可以用装饰器来实现该功能,不推荐

      • 封装
        把客观事物封装成抽象的类, 隐藏实现细节, 使得代码模块化,简单来说定义公开的接口,仅关心获取接口的功能或数据,不关心如何实现

课后作业

  • 用类封装一个MyMath类, 实现加, 减, 乘, 除, 幂, 开方

      class MyMath:
      	def add(self, a, b):
      		return a + b
    
      	def subtract(self, a, b):
      		return a - b
    
      	def multi(self, a, b):
      		return a * b
    
      	def divi(self, a, b):
      		return a / b
    
      	def power(self, a, b):
      		return a ** b
    
      	def Prescription(self, a, b):
      		return a ** (1 / b)
    
    
      value = MyMath()
      print(f'加法:', value.add(2, 2))
      print(f'减法:', value.subtract(2, 2))
      print(f'乘法:', value.multi(2, 2))
      print(f'除法:', value.divi(2, 2))
      print(f'幂:', value.power(2, 2))
      print(f'开方:', value.Prescription(2, 2))
  • 自由课题, 大家按自己的想法, 将身边的事物抽象出一个类, 并创建多个实例

    • 创建多个继承作业2父类的子类
      # 定义一个类Message 消息
      # 标题,内容
      class Message(object):
      	message = 'message'
    
      	def __init__(self, title, context):
      		self.t = title
      		self.c = context
    
      	def mes(self):
      		print(f'Title: {self.t}\nContext: {self.c}')
    
    
      # 创建多个继承作业2父类的子类
      class Terminal(Message):
      	def __init__(self, title, context):
      		# title=title 前面的title是Message.self.t=title,后面的是则是Terminal.self.title
      		super(Terminal, self).__init__(title=title, context=context)
    
      	def info(self):
      		# self.t=Message.self.t
      		print(f'{self.t}\t\t{self.c}')
    
      # 继承和多态
      class Test1(Message):
      	def func1(self):
      		pass
    
    
      if __name__ == '__main__':
      	# 小明 = 消息(内容)
      	xiaoming = Message('hello', 'xiaohong')
      	xiaoming.mes()
      	# 小红 = 消息(内容)
      	xiaohong = Message('hello', 'xiaoming')
      	xiaohong.mes()
      	# 终端 =
      	tty = Terminal('tty', 'This is tty')
      	tty.info()

类属性和实例属性

  • 类属性

    • 通过类对象可以直接访问的属性

    • 抽象概念的固有属性, 要考虑当前抽象概念的普适性

      # 贴标签不是一个特别好的抽象, 原因他没有一个普适性
      class Developer:
          programing_language = None
          busy = True
      • 私有属性
        不希望外部更改, 只作用于类内部
        • 通过__变量名来声明私有属性

          class Lottery:
              __items = ["mac", "ipad", "iphone"]
        • 通过类._类名__变量名来访问私有属性

          print(Lottery._Lottery__items)
  • 实例属性

    • 绑定在实例上的属性, 只能通过该实例进行访问

    • 实例的自有属性

      class Developer:
          programing_language = None
          busy = True
          __case = "doing something"
      
      d_python = Developer()
      d_python.programing_language = "python"
      d_java = Developer()
      d_java.programing_language = "java"
      
      print(d_java.programing_language)
      print(d_python.programing_language)
      • 私有属性
        • 通过self.__变量名来声明私有属性
        • 通过实例._类名__变量名来访问私有属性

类方法, 静态方法, 实例方法

  • 类方法

    • 仅供类调用的方法
    • 通过classmethod装饰器来声明一个类方法
    • 自定义类创建
      class Developer:
          programing_language = None
          busy = True
          __case = "doing something"
          def __init__(self, hairs):
              self.__hairs = hairs
      
          @classmethod
          def __new__(cls, *args, **kwargs):
              print("init class")
              return super().__new__(cls)
      
          @classmethod
          def get_case(cls):
              return cls.__case
  • 静态方法

    • 类可以直接调用的方法
    • 通过staticmethod装饰器装饰
    • 对一类抽象行为的归类
      class MyMath:
      
          @staticmethod
          def add(a, b):
              return a + b
  • 实例方法

    • 仅供实例调用的方法

接口, 协议和抽象基类

  • 接口
    对象公开方法的子集, 让对象在系统中扮演特定的角色.

    list实现了增删改查的接口, 只要有一个接口没有实现那就不属于list
    tuple只提供了查的接口
  • 协议
    非正式的接口, 协议与继承没有关系, 一个类可能会实现多个接口, 从而让实例扮演多个角色

    list扮演者列表的角色, 但同时也是一个序列, 序列并不是一个实体类.
    • 协议的应用
      class MyDict(dict):
          def __iadd__(self, other):
              self.update(other)
              return self
      
          def __str__(self):
              return f"My Dict {self.items()}"
  • 抽象基类
    把客观事物封装成抽象的元类, 区分概念和实现.

    • 只要有@abc.abstractmethod装饰器的类就是抽象基类
      import abc
      class Mixin:
          def sign(self):
              pass
      
          def rank(self):
              pass
      
      class Gamer:
          @abc.abstractmethod
          def sign(self):
              pass
      
      
      class GoGamer(Mixin, Gamer):
          pass
      
      class Swimmer(Mixin, Gamer):
          pass

课后作业

  • 将之前封装的MyMath类中的实例方法改为静态方法, 体会两者的区别
class MyMath:
    @staticmethod
    def add(a, b):
        return a + b

    @staticmethod
    def subtract(a, b):
        return a - b

    @staticmethod
    def multi(a, b):
        return a * b

    @staticmethod
    def divi(a, b):
        return a / b

    @staticmethod
    def power(a, b):
        return a ** b

    @staticmethod
    def Prescription(a, b):
        return a ** (1 / b)

   def add_2(self, a, b):
	return a + b
		
	print(f'加法:', MyMath.add(2, 2))
	print(f'减法:', MyMath.subtract(2, 2))
	print(f'乘法:', MyMath.multi(2, 2))
	print(f'除法:', MyMath.divi(2, 2))
	print(f'幂:', MyMath.power(2, 2))
	print(f'开方:', MyMath.Prescription(2, 2))
	
	math = MyMath()
	print(math.add_2(1, 2))
  • 为上节课自定义类添加以下功能:
    • 添加类属性
    • 添加类私有属性
    • 添加类方法或者类的私有属性
    • __init__方法中初始化实例属性
    • __init__方法中绑定私有实例属性
    • 在自定义类中实现__str__, 自定义输出格式
class People:
    name = None #类属性、实例属性
    gender = None 
    __age = 18 #私有属性

    def __init__(self, name, gender):
        self.__name = name #实例私有属性
        self.gender = gender #初始化实例属性
        print(f"姓名:{self.__name}")
        print(f"性别:{self.gender}")

    @classmethod
    def get_age(cls): #类方法
        return cls.__age

    def __str__(self):
        return f"{self.__name}是{self.gender}生"


value = People('张三', '男')
print(f"年龄:{People.get_age()}")
print(value.__str__())
原文地址:https://www.cnblogs.com/final233/p/15751898.html