Python极简笔记(六)---类、模块、包

一、类的创建

定义:类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

1.1 类创建

  • 代码示例
    #类名第一个字母大写
    class Person:				
    	"""此处放置该类的介绍和描述, print(Person.__doc__)查看"""     
    	# 属性:用名词		
    	# private变量:双下划线,仅当前类方法可调用 	 			  
    	__name = 'chuck'			 
    	# protect变量:仅子类与当前类方法可调用
    	_weight = 80	
    	# public变量:公用,对象.变量名 即可调用
    	height = 176									
    		
    	#类内方法:用动词
    	# 实例初始化:python内建魔法函数,双侧双下划线,见后续解释
    	# self:若需用本类方法或变量,需传入self
    	def __init__(self , name):		
    		# __init__方法不能包含return语句
    		self.__name = name 			
    	
    	# private方法:仅当前类可调用,双下划线
    	def __checkSth():			
    		# pass:若需要暂时搁置细化函数逻辑功能,可只写此关键字
    		print("checkSth is called")
    
    	# protect方法:仅当前类和派生类可调用,单下划线,实际跟public方法
    	#             无使用功能差别,只给编程提供标识的吧
    	def _checkSmb():				
    		print("_checkSmb is called")
    	
    	# public方法:调用无限制,若需用本类方法或变量,需传入self
    	def showDetails(self):			
    		print('name is',self.__name,'hight is',self.height) 				
    

1.2 类的实例化

  • 代码示例
    # 创建实例p:数据类型为class Person,
    # 		自动调用魔法方法__init__方法初始化类对象
    # 		__init__方法隐含调用__new__方法
    p = Person('duke')				
    # 调用类的方法
    p.showDetails()
    >>>'name is duke height is 176'
    
    # 可见protect并不能约束类外调用
    p._checkSth()
    >>> checkSth is called
    
    p.__checkSmb()
    >>> AttributeError: 'Person' object has no attribute '__checkSth'
    
    # 类外使用类内的public变量:建议还是通过类内方法修改
    print(p.height)					
    >>>176
    
    # 修改实例属性:仅此实例变化,其他实例及类本身不变
    p.height = 180					
    print(p.height)	
    >>>180
    
    # 删除实例属性,类的属性就恢复了
    del p.height					
    print(p.height)
    >>>176
    
    # 可见protect并不能约束类外调用
    print(p._weight)					
    >>> 80
    
    # 私有变量调用报错
    print(p.__name)
    >>> AttributeError: 'Person' object has no attribute '__name'
    

二、类继承

2.1 继承

  • 继承规则:派生类与基类同名方法,派生类覆盖基类
  • 继承写法
    class A:
        def __init__(self):
            print("INIT A")
    
    
    class B(A):
        def __init__(self, y):
            print("INIT B y is " + y)
            # 调用基类方法:此处调用A的初始化函数
            # super方法隐含参数:super(B, self)
            super().__init__()
    
    
    class C(B):
        def __init__(self, x, y):
            print("INIT C x is " + x + ", y is " + y)
            # 调用B的初始化函数
            # super方法隐含参数:super(C, self)
            super().__init__(y)
    
    p = C("A", "B")
    >>> INIT C x is A, y is B
    >>> INIT B y is B
    >>> INIT A
    
  • 判断类关系
    # 判断前者是否为后者的派生类
    issubclass(B, A)
    >>> True
    # 判断实例是否属于某个类
    p = B()
    isinstance(p, A)
    >>> True
    isinstance(p, B)
    >>> True
    

2.2 类魔法函数

  • 概述:写法__方法名__,Python的类里提供的,魔法方法会在恰当的时候自动被调用执行,名字固定
  • 类魔法函数列表
     dir(__build_class__)
     
    ['__call__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', \
    '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', \
    '__init_subclass__', '__le__', '__lt__', '__module__', '__name__', '__ne__', \
    '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', \
    '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__text_signature__']	
    

2.2.1 initstrcall

  • 代码示例
    class A:
    	# __init__:类初始化函数,其默认调用__new__
    	# __del__:当对象被销毁时自动调用
    	def __init__(self, num = 18):
    		self.num = num
    	# 返回字符串:若无此语句,打印对象内存地址
        def __str__(self):
            return '调用__STR__语句'
        # 回调函数:实例对象后接小括号触发执行,进阶用法见2.2.6节
    	def __call__(self):
    		print('调用__call__语句')
    ############################################
    # 调用__str__
    p = A()
    print(p)
    >>> 调用__str__语句
    
    # 调用__call__
    p()
    >>> 调用__call__语句
    

2.2.2 比较运算符

  • 代码示例
    class A:
        def __init__(self, num=18):
            self.num = num
            
        # 若没有比较运算符重载语句,则报错
        # ==和!=若无比较运算符重载语句,比较类对象内存地址
        def __gt__(self, other):
            return self.num > other.num
    ############################################
    p1 = A(10)
    p2 = A(11)
    print(p1 > p2)
    >>> False
    

    比较运算符:相等== eq、大于等于>= gt、不等于 != ne、小于等于<= le、大于 > gt、小于< lt


2.2.3 算数运算符

  • 代码示例
    class A:
        def __init__(self, num=18):
            self.num = num
            
        # 若没有算数运算符重载语句,则报错
        def __add__(self, other):
            return self.num + other
    ############################################	
    p1 = A(10)
    print(p1 + 1)
    >>> 11
    

    算数运算符:加+add、减-sub、乘*mul、除/truediv、取余%mod、指数**pow


2.2.4 类型转换运算符

  • 代码示例
    class A:
        def __init__(self, num=18):
            self.num = num
    	
        def __float__(self):
            return self.num * 1.0
    ############################################
    p1 = A(10)
    print(float(p1))
    

    类型转换运算符:整型int、浮点型float、字符串str、布尔型bool

2.2.5 实例中迭代属性

  • 代码示例
    class A:
        def __init__(self, num):
            self.num = num
    
        # 迭代器语句:若有next语句则返回self即可
        def __iter__(self):
            return self
    
        # 生成器的next语句
        def __next__(self):
            # 生成器越界语句
            if self.num >= 20:
                raise StopIteration
            self.num += 1
            # 注意返回值
            return self.num
    ############################################	
    p = A(10)
    # 使用迭代器详见上一篇
    print(list(p))
    >>> [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
    

2.2.6 call实现装饰器

  • 装饰器定义及函数装饰器详见上一篇
  • 不带参数装饰器
    class Decorator:
    
        def __init__(self, func):
            self._func = func
    
        def __call__(self, *args, **kwargs):
            print("此处为新增的逻辑内容")
            # 被装饰函数
            return self._func(*args, **kwargs)
    #############################################
    # 等价于Decorator(test)
    @Decorator
    def test(x):
        print("传入test函数x:", x)
    
    
    if __name__ == '__main__':
        test(1)
    
    >>> 此处为新增的逻辑内容
    >>> 传入test函数x: 1
    
  • 带参数装饰器
    class Decorator:
    
        def __init__(self, state):
        	# 此处接收装饰器传入参数,任何位置都可以使用
            self._state = state
    
        def __call__(self, func):
            self.func = func
            return self.__callback
    
        def __callback(self, *args, **kw):
            print("装饰器传入的参数:", self._state)
            print("此处为新增的逻辑内容")
            return self.func(*args, **kw)
    
    ###################################################
    # @行意思:Decrator('execute')(test)(x)
    @Decorator('execute')
    def test(x):
        print("传入test函数x:", x)
    
    
    if __name__ == '__main__':
        test(1)
    
    ###################################################
    >>> 装饰器传入的参数: execute
    >>> 此处为新增的逻辑内容
    >>> 传入test函数x: 1
    

三、模块、包

3.1 模块

  • 定义:python文件即为模块,如hello.pyhello为模块名,可以在其他程序中导入调用
  • 标准写法:hello.py
    # 开头两行注释为必要注释:
    # 	首行注释:Linux环境中可使用命令:以  ./程序文件名  的方法执行
    # 	次行注释:表示.py文件本身编码使用UTF-8
    ##########################################################
    # !/usr/bin/env python3.6	
    # -*- coding: utf-8 -*-		
    
    # 显示方法:help(hello)或hello.__doc__显示
    ''' 模块的功能及变量说明 '''					
    # 使用__author__变量把作者写入模块
    __author__ = 'duke'				
    
    # 模块语句(含from...improt、类定义、函数定义、全局变量定义)		
    
    # 主语句:当模块为程序入口时,其__name__为'__main__'
    #		否则__name__为模块名,此处为'hello'
    if __name__=='__main__':	
    	# 测试函数,像自动化输入一些参数测试模块		
    	test()							
    
  • 导入及调用模块
    # 方法1:导入模块,模块名不加后缀,中括号为可选
    import 模块名 [as 别名]				
    
    # 方法2:导入模块中的特定函数、类
    from 模块名 import 函数名或类名	
    
    # 方法3:相对路径导入,有限制,见3.3节包相对导入
    from .. import 模块名
    
    
    # 调用模块中函数
    变量 = 模块名.函数名或类名()	#方法 1、3
    变量 = 别名.函数名或类名()		#方法 1 
    变量 = 函数名或类名()			#方法 2	
    

3.2 模块导入示例

  • E:\main\main.py
    # 两种写法演示
    from three import test
    import three
    
    
    if __name__ == '__main__':
        print("main path:" + __file__)
        print("main name:" + __name__)
        test()
    
  • E:\main\three.py
    def test():
    	# 显示__file__变量所在模块的绝对路径
    	# 找模块文件夹用
        print("three path:" + __file__)
        # 显示模块名称
        print("three name:" + __name__)
    
  • 输出
    # win 10 输出
    main path:E:/main/main.py
    main name:__main__
    three path:E:\main\three.py
    three name:three
    
    # centos 输出
    main path:main.py
    main name:__main__
    three path:/root/main/three.py
    three name:three
    
    # mac 输出
    main path:/main/main.py
    main name:__main__
    three path:/main/three.py
    three name:three
    

3.3 包

  • 定义:一种管理 Python 模块命名空间的组织形式,目的为了模块管理

  • 目录结构示意(蓝色为文件夹)

    • __ init__.py:包标识文件,可为空,也可以执行包的初始化代码或设置__all__变量
    • all变量:在__init__.py中定义列表 __all__ = ["函数名", "类名"]from 包名 import *会加载此列表
  • 系统路径

    In [1]: import sys
    # 包需要在系统搜索路径下,否则会报错
    In [2]: sys.path
    Out[2]: 
    ['/usr/local/bin',
     '/usr/lib64/python36.zip',
     '/usr/lib64/python3.6',
     '/usr/lib64/python3.6/lib-dynload',
     # 空路径:代表当前执行的程序的**入口程序文件**的父目录
     '',
     '/usr/local/lib64/python3.6/site-packages',
     '/usr/local/lib/python3.6/site-packages',
     '/usr/lib64/python3.6/site-packages',
     '/usr/lib/python3.6/site-packages',
     '/usr/local/lib/python3.6/site-packages/IPython/extensions',
     '/root/.ipython']
    
  • 包调用

    # 方法1:指定模块,中括号可选
    import 包名.模块名 [as f]
    # 调用包中的函数
    f.函数名()
    模块名.函数名()
    # 调用包中的类
    f.类名()
    模块名.类名()
    
    ############################################
    # 方法2:指定到模块中的函数、类
    from 包名.模块名 import 函数名1,函数名2,类名1
    # 调用包中的函数
    函数名1()
    # 调用包中的类
    类名1()
    
    ############################################
    # 方法3:嵌套包
    from 包名.子包名1.模块名 import 函数名1,类名1
    # 调用包中的函数
    函数名1()
    # 调用包中的类
    c = 类名1()
    ############################################
    # 方法4:相对路径导入,常用于子包中
    from ..父包名 import 父包中的模块名
    

3.4 程序模块组织

  • 示例架构
    在这里插入图片描述

3.4.1 同级独立模块导入

  • 代码示例
    #################################
    # 		main.py文件代码内容		#
    #################################
    
    # 方法1:直接导入模块
    import main_bro
    # 方法2:使用模块别名
    from main_bro import test as main_bro_test
    
    # 每个模块都是这个写法,都打印模块名字
    def test():
        print("this is main")
    
    if __name__ == '__main__':
        test()
        # 方法1
        main_bro.test()
        # 方法2
        main_bro_test()
    
    
    ################################
    # 输出
    >>> this is main
    >>> this is main_bro
    >>> this is main_bro
    

3.4.2 独立模块导入包内模块

  • 代码示例
    #################################
    # 		main.py文件代码内容		#
    #################################
    from pack02 import module_02
    from pack02.module_02 import test as module_02_test
    
    
    def test():
        print("this is main")
    
    
    if __name__ == '__main__':
        test()
        module_02.test()
        module_02_test()
    
    
    ################################
    >>> this is main
    >>> this is module_02
    >>> this is module_02
    

3.4.3 异包互导

  • 代码示例
    #################################
    # 		main.py文件代码内容		#
    #################################
    from pack01.pack11.pack111.module_111 import test
    
    if __name__ == '__main__':
        test()
    
    
    #################################
    # 	module_111.py文件代码内容		#
    #################################
    from pack02.module_02 import test
    
    if __name__ == '__main__':
        test()
    
    
    ################################
    >>> this is module_02
    

3.4.4 同包 子 导入 父(推荐)

  • 代码示例
    #################################
    # 		main.py文件代码内容		#
    #################################
    from pack01.pack11.pack111.module_111 import test
    
    if __name__ == '__main__':
    	test()
    
    #################################
    # 	module_111.py文件代码内容		#
    #################################
    from pack01.module_01 import test
    
    if __name__ == '__main__':
        test()
    
    ################################
    >>> this is module_01
    

3.4.5 同包 子 导入 父(相对导入)

  • 同包 子包 导入 长辈包(相对导入)
    #################################
    # 		main.py文件代码内容		#
    #################################
    from pack01.pack11.pack111.module_111 import test
    
    if __name__ == '__main__':
    	test()
    
    #################################
    # 	module_111.py文件代码内容		#
    #################################
    # 代表: 单点--当前文件的父文件夹(省略)
    #		双点--当前文件的祖父文件夹
    # 		三点--当前文件的曾祖父文件夹,以此类推无限点下去
    # 注意:模块不是路径没有斜杠‘/’,且点紧贴模块名
    # 通常不用记,按照点出来的软件提示选即可
    from ..module_11 import test
    
    # 相对导入,此语句失效,即本程序文件不可直接运行
    if __name__ == '__main__':
        test()
    
    ################################
    >>> this is module_11
    
  • 适用环境:三层以下,用3.4.4节,超过三层,最深层的可以考虑用相对导入
  • 异常
    • 不能直接运行,否则报错:ImportError: attempted relative import with no known parent package
    • 不可越顶级包,否则报错:ValueError: attempted relative import beyond top-level package

      越顶级包:即module_01中from ..main_bro import test,引用pack02也同样为越级

3.4.6 总结

  • 同级模块导入,直接import 模块名
  • 非同级模块导入:直接from 包名.包名......包名 import 模块
  • 深层包或者偷懒:按提示使用from ..模块名 import 函数名,尽量少用

回到总目录

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值