python基础(一)数据结构、控制流、函数:https://blog.csdn.net/runafterhit/article/details/94908703
(1)类:定义类是通过class关键字完成。类似c++,类由数据(属性)和函数(方法)的组成,使用dir(‘类名’)可以查看类的全部属性和方法,创建一个新类意味着创建该类型的实例,也叫类的实例化 。每个类都带有一个__init__函数,在实例时调用对类进行初始化,类似C++构造函数。
(2)python类继承机制允许多个基类,派生类可以覆盖它基类的任何方法,一个方法可以调用基类中相同名称的的方法。对象可以包含任意数量和类型的数据。和模块一样,类也拥有 Python 天然的动态特性:它们在运行时创建,可以在创建后修改。
(3)访问限制,属性的名称前加上两个下划线__,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。(实际的实现就是给名字加了字段修改了名字,不同版本字段不同)
class Dog:def __init__(self): #self 表示创建的实例本身,类似this指针self.color = 'while' # 定义属性 白色self.__name = 'peter' # 定义私有属性def eat(self): # 定义方法,没有self相当于静态方法,只能通过类对象调用print ('i am is eat\n')my_dog = Dog() # 类 的 实例化
my_dog.eat() # 输出 i am is eat
my_dog.__name # 编译报错 'Dog' object has no attribute '__name'
>>> dir ('str')
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isascii', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
(1)封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,将抽象得到的数据和行为(或功能)相结合,目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。
(2)继承 :以一个类为基础创建新的类,子类会继承父类的全部属性和方法,继承机制可以很好的描述一个类的生态,也提高了代码复用率。
(3)多态:多态其实是在继承的基础上的,指一个类实例(对象)的相同方法在不同情形有不同表现形式,实现多态有二种方式,覆盖,重载。覆盖,是指子类重新定义父类的虚函数的做法。重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
class Ball:def __init__(self, size, color): self.size = sizeself.color = color def setName(self, name):self.name = namedef play(self):print('play ball\n')class BasketBall(Ball):def __init__(self): super().__init__(10, 'red') # super可以引用父类的def play(self):print('play basketball\n')def shootBall(self):print ('shoot the basketball\n')myBasketball = BasketBall()
myBasketball.setName('myBasketball') # 继承ball的方法
print (myBasketball.name) # 输出 myBasketball
myBasketball.shootBall() # 子类新增的方法,输出 shoot the basketball
myBasketball.play() # 覆盖了父类方法,输出 play basketball
(1)python的类,类对象,实例对象的关系。
当定位完类后,直接对类名.属性/方法 进行操作 表示 针对类对象操作。对类进行实例化创建该类的实例对象,对实例对象操作为对实例的操作行为。绝大部分情况下,大家都应该对实例进行操作 ,而非对类对象进行操作。
定义属性时,类下声明的类属性,实例对象可以调用这个变量但不能修改,只有类对象才有资格修改类的属性。实例对象尝试修改了类属性,实际是创建了一个实例的新属性。
class MyCnt:count = 10 #类属性 可以由所有对象访问,但实例对象不能修改,类对象可以def __init__(self):self.instance_count = 0 # (实例)对象属性,每个实例对象各自的属性a = MyCnt() # 创建3个实例对象
b = MyCnt()
c = MyCnt()c.count += 10 # 修改了类属性,实际是创建了一个实例的新属性
print (a.count) # 输出 10
print (b.count) # 输出 10
print (c.count) # 输出 20
MyCnt.count += 20 # 操作 类对象 操作 类属性
print (a.count) # 输出 30
print (b.count) # 输出 30
print (c.count) # 输出 20 ,由于是实例的属性,并未被修改
任何一个大型项目 都会拆解为各种模块,通过各自的源文件管理。
模块:一个包含Python定义和语句的文件。文件名就是模块名后跟文件后缀 .py 。在一个模块内部,模块名(作为一个字符串)可以通过全局变量 name 的值获得。直接执行的入口文件__name__ 为__main__,因此也可以通过是否为main来确定是单独执行当前文件 还是被调用,可以辅助作为自测文件判断条件 进行测试。
def get_max(num1, num2):if num1 >= num2:return num1else:return num2def test():print ('the max in 1 , 2 is ' + str(get_max(1, 2)))if __name__ == '__main__':test()
包:可以理解为管理 包含子包(子文件夹)和 模块 (python文件)的 文件夹 抽象。
包是一种通过用“带点号的模块名”来构造 Python 模块命名空间的方法,能很好的解决模块过多后模块重命名问题。块名 A.B 表示 A 包中名为 B 的子模块。必须要有 init.py 文件才能让 Python 将包含该文件的目录当作包。在最简单的情况下__init__.py 可以只是一个空文件。
sound/ Top-level package__init__.py Initialize the sound packageformats/ Subpackage for file format conversions__init__.pywavread.pywavwrite.pyaiffread.py...filters/ Subpackage for filters__init__.pyequalizer.pyvocoder.py...
模块被导入的时候,解释器首先寻找具有该名称的内置模块,非内置模块的导入会按照系统路径进行查找导入,可以通过sys.path查看。
导入方式如下:(1)通过import 模块名 可以导入模块;用模块名引用模块中的函数,如fibo.fib(1000)。(2)使用from 模块名 import 函数名称,此时可以直接使用该函数,如fib(1000),此处可以使用*通配符来引用某个模块的全部函数如 from fibo import *,但是不建议这样使用防止冲突覆盖。(3)使用 import 模块名 as 新命名空间,可以使用新命名空间来引用函数。
#当fibo模块中存在一个fib函数 需要使用
import fibo # 可以用模块名fibo引用模块中的函数,如fibo.fib(1000)
from fibo import fibo # 可以直接使用函数名进行访问,fib(1000)
import fibo as fo # 可以用新命名空间fo引用模块中的函数,如fo.fib(1000)
包的导入类似模块。
import sound.effects.echo # 这会加载子模块 sound包中的effects包的echo模块 ,但引用它时必须使用它的全名
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
from sound.effects import echo # 加载子模块 echo ,并使其在没有包前缀的情况下可用
echo.echofilter(input, output, delay=0.7, atten=4)
from sound.effects.echo import echofilter # 直接导入函数
echofilter(input, output, delay=0.7, atten=4)
异常与错误:解析脚本过程语法错误又称解析错误,在执行脚本语句过程检测到的错误被称为异常,比如除0或者打开文件失败。python的异常处理相关语句主要包括:1、异常捕获try expect语句 2、异常抛出 raise语句 。
异常有不同的类型,而其类型名称将会作为错误信息的一部分中打印出来。所有异常必须为一个派生自 BaseException 的类的实例。常见的内置异常类型如下:
AssertionError:当 assert 语句失败时将被引发;
IndexError:当序列抽取超出范围时将被引发;
KeyboardInterrupt:当用户按下中断键 (通常为 Control-C 或 Delete) 时将被引发
MemoryError:当一个操作耗尽内存但情况仍可(通过删除一些对象)进行挽救时将被引发。
NameError:当某个局部或全局名称未找到时将被引发
OSError:系统函数错误引发,如 I/O 操作失败 "文件未找到" 或 "磁盘已满" 等
ZeroDivisionError:当除零时错误将被引发
通过try expect (else)(finally)来捕捉过程抛出的异常,然后进行处理,else和finally为可选子句,finally用于定义必须在所有情况下执行的清理操作。
原理如下:执行 try 子句 (try 和 except 关键字之间的(多行)语句),如果没有异常发生,则跳过 except 子句 并完成 try 语句的执行。如果发生了异常,则跳过该子句中剩下的部分。然后如果异常的类型和 except 关键字后面的异常匹配,则执行 except 子句 ,然后继续执行 try 语句之后的代码。如果发生的异常和 except 子句中指定的异常不匹配,则将其传递到外部的 try 语句中;如果没有找到处理程序,则它是一个 未处理异常,执行将停止并显示错误消息。如果由finally语句,发生异常后一定会执行( 常用于用于保证资源释放);
try:f = open("not exit file")print(f.read())f.close()
except ValueError: # 捕捉系统ValueError异常类型print ("ValueError")
except (TypeError, ZeroDivisionError): # 捕捉系统多种异常print ("TypeError or ZeroDivisionError")
except OSError as reason: # 捕捉系统OS异常类型print ("这里错误原因:" + str(reason))
except :print ('process exception')
else : # (可选语句)没有异常的时候处理流程print ('no error')
finally: # (可选语句)无论如何都会执行的代码,可用于回收资源等print ('error end, release the resoure\n')
# 输出 :
#这里错误原因:[Errno 2] No such file or directory: 'not exit file'
#error end, release the resoure
raise 语句允许程序员强制发生指定的异常。raise 唯一的参数就是要抛出的异常。这个参数必须是一个异常实例或者是一个异常类(派生自 Exception 的类)。如果传递的是一个异常类,它将通过调用没有参数的构造函数来隐式实例化。
try:raise NameError('HiThere')
except NameError as reasion:print('exception NameError:' + str(reasion))# 输出 exception NameError:HiThere