学习这件事不在乎有没有人教你,最重要的是在于你自己有没有觉悟和恒心。————法布尔

编程

Python面向对象-包-模块学习笔记(七)

  • 2020-01-15 16:07
简介 :学学python oop编程跟包,模块的特性, 笔记懒得整理了.直接零碎了. 哈哈哈

Python 类学习记录

Python 使用变量(类中属性)前必须赋值, py变量没有默认值 , 并且没有私有方法或属性一说, 伪造私有效果就是在命名方法或属性的时候前面添加双下划线 def __aa() __usename

比如:

  • class Secretive:
  • def __inaccessible(self):
  • print("Bet you can't see me ...")
  • def accessible(self):
  • print("The secret message is:")
  • self.__inaccessible()
  • s = Secretive()
  • a.__inaccessible() # 报错

其实py内部处理这个方式并不标准, 类在定义的时候,对所有以两个下划线进行定义的名称进行转化,即在开头加上一个下划线跟类名 _class__method() 或属性 , 只要知道这种幕后手法,就可以访问私有方法

  • # 上面的demo
  • s = Secretive()
  • s._Secretive__inaccessible() # 就可以访问私有属性了

另一个实现私有方式 from moudle import *不会导入以一个下划线符号开头的名称.一定程度来说, 一个下划线,跟两个下划线开头的实现了不同程度的类私有属性

类的命名空间

  • #下面两条语句大致等价:
  • def foo(x): return x * x # 全局函数理解为
  • foo = lambda x: x * x # 这玩意可以理解为py的闭包 关键字 lambda
  • class demo(object): # 他的使用范围就在class 中 , 这笔记有点鸡肋了哈哈
  • def foo(self,x):
  • return x*x

类的奇葩

  • class demo(object): # 不用写属性或方法直接写这个玩意, 或者pass
  • print('hello world')
  • class demo2(object):
  • pass

类的继承

class test(demo): test 继承了demo

多继承

class test(demo1, demo2): 需要注意的是 demo1 demo2 如果这两个类中有相同的方法名称, 那么谁在前面,谁会覆盖后面的

类常见函数

  1. issubclass(class1,class2) 判断类1是否是类2的子类

  2. 查看类的基类 __bases__ class1.__bases__

  3. 检查方法是否存在 hasattr(demo(),'aa') 私有方法也检测不到(也就是双下划线开头滴)

  4. isinstance(object, class) 确定对象是否是指定类的实例

  5. callable(object) 判断对象是否是可调用的(如是否是函数或方法)

  6. getattr(object,name[,default]) 获取属性的值,还可提供默认值

  7. hasattr(object, name) 确定对象是否有指定的属性

  8. setattr(object, name, value) 将对象的指定属性设置为指定的值

构造函数

def __init__(self):

析构函数

def __del__(self):

调用父级构造函数或其他

基类.__init__(self) 或者 super().__init__()

常用魔术方法

__getattribute__(self, name): 在属性被访问时自动调用(只适用于新式类)。 __getattr__(self, name): 在属性被访问而对象没有这样的属性时自动调用。 __setattr__(self, name, value): 试图给属性赋值时自动调用。 __delattr__(self, name): 试图删除属性时自动调用。

抽象基类

  • from abc import ABC, abstractmethod
  • class Talker(ABC):
  • @abstractmethod #形如这个@xxx 称为py的装饰器
  • def talk(self):
  • pass

静态属性跟类方法

作用:静态方法的定义中没有参数self,可直接通过类来调用。 也可以直接使用类实例调用 , 但是静态目的就是不实例化,所以直接类名调用即可

方式一:

  • class test:
  • def static():
  • print('this is status method')
  • # 静态方法不需要self 参数,并且使用staticmethod进行声明
  • static = staticmethod(static)
  • def cmeth(cls):
  • print('This is a class method of', cls)
  • # 类方法如果包含self 参数通常命名cls
  • cmeth = classmethod(cmeth)

方式二:

上述定义比较繁琐,也不优雅py2.4添加了装饰器的修饰方式

  • class MyClass:
  • @staticmethod # 静态方法
  • def smeth():
  • print('This is a static method')
  • @classmethod # 类方法
  • def cmeth(cls):
  • print('This is a class method of', cls)
  • #装饰器可用于包装任何可调用的对象,并且可用于方法和函数。

python模块

import 为何只导入模块一次?

书中这么解释的:

在大多数情况下,只导入一次是重要的优化,且在下述特殊情况下显得尤为重要:两个 模块彼此导入对方。 在很多情况下,你可能编写两个这样的模块:需要彼此访问对方的函数和类才能正确地 发挥作用。例如,你可能创建了两个模块clientdbbilling,分别包含客户数据库和记账系 统的代码。客户数据库可能包含对记账系统的调用(如每月自动向客户发送账单),而记账系 统可能需要访问客户数据库的功能才能正确地完成记账。 在这里,如果每个模块都可导入多次,就会出现问题。模块clientdb导入billing,而 billing又导入clientdb,结果可想而知:最终将形成无穷的导入循环。 然而,由于第二次导入时什么都不会发生,这种循环被打破。 如果一定要重新加载模块,可使用模块importlib中的函数reload,它接受一个参数(要 重新加载的模块),并返回重新加载的模块。如果在程序运行时修改了模块,并希望这种修改 反映到程序中,这将很有用。

当你导入模块时,可能发现其所在目录中除源代码文件外,还新建了一个名为__pycache__ 的子目录(在较旧的Python版本中,是扩展名为.pyc的文件)。这个目录包含处理后的文 件, Python能够更高效地处理它们。以后再导入这个模块时,如果.py文件未发生变化, Python将导入处理后的文件,否则将重新生成处理后的文件。删除目录__pycache__不会 有任何害处,因为必要时会重新创建它.

如何检测模块是作为程序运行的还是被模块导入的?

__name__

module.__name__ == '__main__' 作为程序运行

module.__name__ == 'module' 如果等于模块名则作为模块导入的

总结: 模块说白了就是个被其他程序引入的py文件.

python 包

包其实是另一种形式的模块,只不过包可以包含其他模块,是由一个或多个模块做成的,物理层面上说,包是一个目录, 某块是一个py文件

包跟目录的区别是, 包必须包含一个__init__.py 的包初始文件 , 这个文件就是包的的内容

书中案例:

包的目录结构

  • ~/python/ PYTHONPATH中的目录
  • ~/python/drawing/ 包目录(包drawing)
  • ~/python/drawing/__init__.py 包代码(模块drawing)
  • ~/python/drawing/colors.py 模块colors
  • ~/python/drawing/shapes.py 模块shape

引入包

import drawing # (1) 导入drawing包,可使用目录drawing中文件__init__.py的内容,但不能使用模块shapescolors的内容。

import drawing.colors # (2) 导入drawing包中的模块colors , 可使用模块colors,但只能通过全限定名drawing.colors方式来使用。

from drawing import shapes # (3) 导入模块shapes , 可使用简化名(即shapes)来使用模块shapes

sys 模块

模块sys让你能够访问与Python解释器紧密相关的变量和函数,如果cli模式参数啥的.

  • argv #命令行参数,包括脚本名
  • exit([arg]) #退出当前程序,可通过可选参数指定返回值或错误消息
  • modules #一个字典,将模块名映射到加载的模块
  • path #一个列表,包含要在其中查找模块的目录的名称
  • platform #一个平台标识符,如sunos5或win32
  • stdin #标准输入流——一个类似于文件的对象
  • stdout #标准输出流——一个类似于文件的对象
  • stderr #标准错误流——一个类似于文件的对象

os 模块

模块os让你能够访问多个操作系统服务。

  • environ #包含环境变量的映射
  • system(command) #在子shell中执行操作系统命令
  • sep #路径中使用的分隔符
  • pathsep #分隔不同路径的分隔符
  • linesep #行分隔符('\n'、 '\r'或'\r\n')
  • urandom(n) #返回n个字节的强加密随机数据

fileinput 模块

感觉这个比较得劲记录波

  • input([files[, inplace[, backup]]]) #帮助迭代多个输入流中的行
  • filename() #返回当前文件的名称
  • lineno() #返回(累计的)当前行号
  • filelineno() #返回在当前文件中的行号
  • isfirstline() #检查当前行是否是文件中的第一行
  • isstdin() #检查最后一行是否来自sys.stdin
  • nextfile() #关闭当前文件并移到下一个文件
  • close() #关闭序列

作用:

  1. 模块fileinput让你能够轻松地迭代一系列文本文件中的所有行。

  2. 你还可在UNIX管道中对使用UNIX标准命令cat提供给标准输入(sys.stdin)的行进行迭代。比如: cat file.txt | awk '$3 >= 3{print $1}' | python some_script.py等, py脚本使用 sys.stdin(如果用sys模块) 返回的可for的迭代对象进行使用分析日志对劲

  3. 如果使用fileinput 模块, 可以使用fileinput.input 返回可迭代对象

Top