Python3 基础
- 15. Python3 数据结构
- 15.1 将列表当做堆栈使用
- 15.2 将列表当作队列使用
- 15.3 列表推导式
- 15.4 遍历技巧
- 16. Python3 异常
- 16.1 异常处理
- 抛出异常
- try/except
- try/except...else
- try-finally
- 用户自定义异常
- 17. Python3 面向对象
- 17.1 面向对象技术简介
- 17.2 类定义
- 17.3 类对象
- __init__()
- 17.4 类的方法
- 17.5 类的继承
- 17.6 方法重写
- super() 函数
- 17.7 类属性与方法
- 18. global 和 nonlocal关键字
- 19. 函数(function)vs 方法(method)
15. Python3 数据结构
15.1 将列表当做堆栈使用
- 列表方法使得列表可以很方便的作为一个
堆栈
来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出
)。 - 用
append()
列表方法可以把一个元素添加到堆栈顶。 - 用不指定索引的
pop()
列表方法可以把一个元素从堆栈顶释放出来。
实例:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
15.2 将列表当作队列使用
- 可以把列表当做队列用,只是在队列里第一加入的元素,第一个取出来。
- 拿列表用作这样的目的效率不高。在列表的最后添加或者弹出元素速度快,然而在列表里插入或者从头部弹出速度却不快(因为所有其他的元素都得一个一个地移动)。
实例:
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
deque:类似列表(list
)的容器,实现了在两端快速添加(append
)和弹出(pop
)。
15.3 列表推导式
- 列表推导式提供了从序列创建列表的简单途径。
- 每个列表推导式都在
for
之后跟一个表达式,然后有零到多个for
或if
子句。 - 返回结果是一个根据表达式从其后的
for
和if
上下文环境中生成出来的列表。 - 如果希望表达式推导出一个
元组
,就必须使用括号
。
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
>>> [[x, x**2] for x in vec]
[[2, 4], [4, 16], [6, 36]]
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> [3*x for x in vec if x > 3]
[12, 18]
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x * y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x + y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i] * vec2[i] for i in range(len(vec1))]
[8, 12, -54]
>>> [str(round(355/113, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
15.4 遍历技巧
- 在字典中遍历时,关键字和对应的值可以使用字典的
items()
方法同时解读出来:
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
print(k, v)
- 在序列中遍历时,索引位置和对应值可以使用
enumerate()
函数同时得到:
for i, v in enumerate(['tic', 'tac', 'toe']):
print(i, v)
- 要同时遍历两个或更多的序列,可以使用
zip()
函数组合:
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
print('What is your {0}? It is {1}.'.format(q, a))
- 要反向遍历一个序列,首先指定这个序列,然后调用
reversed()
函数:
for i in reversed(range(1, 10, 2)):
print(i,end=",")
- 要按顺序遍历一个序列,使用
sorted()
函数返回一个已排序的序列,并不修改原值:
basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
for f in sorted(set(basket)):
print(f,end=",")
16. Python3 异常
-
运行期
检测到的错误被称为异常
。
16.1 异常处理
抛出异常
- Python使用
raise
语句抛出一个指定的异常。 -
raise
语法格式如下:raise [Exception [, args [, traceback]]]
try/except
- 一个
try
语句可能包含多个except
子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。 - 一个
except
子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组
。except (RuntimeError, TypeError, NameError):
pass
- 最后一个
except
子句可以忽略异常的名称,它将被当作通配符使用。你可以使用这种方法打印一个错误信息,然后再次把异常抛出。
try/except…else
-
try/except
语句还有一个可选的else
子句,如果使用这个子句,那么必须放在所有的except
子句之后。 -
else
子句将在try
子句没有发生任何异常的时候执行。
try-finally
-
try-finally
语句无论是否发生异常都将执行最后的代码。
用户自定义异常
- 可以通过创建一个新的异常类来拥有自己的异常。
- 异常类继承自
Exception
类,可以直接继承,或者间接继承。
实例: repr()
: 产生一个解释器易读的表达形式。返回一个对象的string
格式。
17. Python3 面向对象
17.1 面向对象技术简介
-
类(Class)
:用来描述具有相同
的属性
和方法
的对象
的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例
。 -
方法
:类中定义的函数。 -
类变量
:类变量在整个实例化的对象中是公用的。类变量定义在类中
且在方法体之外
。类变量通常不作为实例变量使用。 -
数据成员(属性)
:数据成员可以大致分为两类:属于对象的数据成员和属于类的数据成员。
1)属于对象的数据成员一般在构造方法__init__()
中定义,当然也可以在其他成员方法中定义,在定义和在实例方法中访问数据成员时以self
作为前缀,同一个类的不同对象(实例)的数据成员之间互不影响;
2)属于类的数据成员是该类所有对象共享的,不属于任何一个对象,在定义类时这类数据成员一般不在任何一个成员方法的定义中。 -
方法重写
:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override)
,也称为方法的重写
。 -
局部变量
:定义在方法中的变量,只作用于当前实例的类。 -
实例变量
:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用self
修饰的变量。 - 继承:即一个派生类
(derived class)
继承基类(base class)
的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。 -
实例化
:创建一个类的实例,类的具体对象。 -
对象
:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
17.2 类定义
- 语法格式
class ClassName:
<statement-1>
.
.
.
<statement-N>
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
17.3 类对象
#!/usr/bin/python3
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
以上创建了一个新的类实例并将该对象赋给局部变量x,x为空的对象。
init()
- 类有一个名为
__init__()
的特殊方法(构造方法),该方法在类实例化
时会自动调用。
def __init__(self):
self.data = []
- 实例化类
MyClass
,对应的__init__()
方法就会被调用:x = MyClass()
。 __init__()
方法可以有参数,参数通过__init__()
传递到类的实例化操作上。
#!/usr/bin/python3
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
17.4 类的方法
在类的内部,使用def
关键字来定义一个方法
,与一般函数定义不同,类方法
必须包含参数self
,且为第一个参数,self
代表的是类的实例
。
#!/usr/bin/python3
# 类定义
class people:
# 定义基本属性
name = ''
age = 0
# 定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
# 定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('runoob',10,30)
p.speak()
17.5 类的继承
#!/usr/bin/python3
# 类定义
class people:
# 定义基本属性
name = ''
age = 0
# 定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
# 定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
# 重写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
# 另一个类,多重继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
# 多重继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中排前地父类的方法
17.6 方法重写
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
super() 函数
-
super()
内置函数是用于调用父类(超类)的一个函数。 - 对于定义的每一个类,
Python
会计算出一个方法解析顺序(MRO
)列表。这个MRO
列表就是一个简单的所有基类的线性顺序表。
class A():
def __init__(self):
print("Enter A")
class B(A):
def __init__(self):
print("Enter B")
super(B,self).__init__()
print("Leave B")
class C(A):
def __init__(self):
print("Enter C")
super(C,self).__init__()
print("Leave C")
class D(B,C):
def __init__(self):
print("Enter D")
super(D,self).__init__()
print("Leave D")
print(D.mro())
print(D.__mro__)
17.7 类属性与方法
- 类的私有属性
__private_attrs
:两个下划线开头,声明该属性为私有
,不能在类的外部被使用或直接访问。在类内部的方法中使用时self.__private_attrs
。
#!/usr/bin/python3
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
- 类的方法
- 在类的内部,使用
def
关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self
,且为第一个参数,self
代表的是类的实例。 -
self
的名字并不是规定死的,也可以使用this
,但是最好还是按照约定是用self
。
- 类的私有方法
__private_method
:两个下划线开头,声明该方法为私有方法
,只能在类的内部调用,不能在类的外部调用。self.__private_methods
。
#!/usr/bin/python3
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('菜鸟教程', 'www.runoob.com')
x.who() # 正常输出
x.foo() # 正常输出
x.__foo() # 报错
18. global 和 nonlocal关键字
- 当局部作用域想修改全局作用域的变量时,需要使用
global
关键字。以下实例修改全局变量num
:
#!/usr/bin/python3
num = 1
def fun1():
global num # global 关键字声明
print(num)
num = 123
print(num)
fun1()
print(num)
- 如果要修改
嵌套作用域
(enclosing
作用域,外层非全局作用域
)中的变量则需要使用nonlocal
关键字。
#!/usr/bin/python3
num = 1
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()
print(num)
19. 函数(function)vs 方法(method)
- 函数是直接写在文件中而不是
class
中,方法是只能写在class
中。 - 与类和实例无绑定关系的
function
都属于函数(function
)。定义方式:def
函数名([形参]) - 与类和实例有绑定关系的
function
都属于方法(method
)。定义方式:def
函数名([形参])。
- 在
class
内定义的实例方法,它第一个参数必须是self
。例:def method(self)
-
Python
支持使用类名调用实例方法,但此方式需要手动将对象传值给self
。例:类名.method(对象名)
- 在
class
内定义的类方法,它第一个参数必须是cls
,它与类class
本身是绑定关系。
- 类方法推荐使用类名直接调用,当然也可以使用实例对象来调用(不推荐)。
- 类方法需要使用
@classmethod
修饰符进行修饰,示例:
@classmethod
def method(cls):
- 在
class
内定义的静态方法,没有类似self
、cls
这样的特殊参数,和函数唯一的区别是:静态方法定义在类这个空间(类命名空间)中,而函数则定义在程序所在的空间(全局命名空间)中。
- 静态方法需要使用
@staticmethod
修饰,示例:
@staticmethod
def static_method():
- 静态方法的调用,既可以使用类名,也可以使用类对象。