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之后跟一个表达式,然后有零到多个forif子句。
  • 返回结果是一个根据表达式从其后的forif上下文环境中生成出来的列表。
  • 如果希望表达式推导出一个元组,就必须使用括号
>>> 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 遍历技巧

  1. 字典中遍历时,关键字和对应的值可以使用字典的items()方法同时解读出来:
knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.items():
    print(k, v)
  1. 在序列中遍历时,索引位置和对应值可以使用enumerate()函数同时得到:
for i, v in enumerate(['tic', 'tac', 'toe']):
    print(i, v)
  1. 同时遍历两个或更多的序列,可以使用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))
  1. 反向遍历一个序列,首先指定这个序列,然后调用reversed()函数
for i in reversed(range(1, 10, 2)):
    print(i,end=",")
  1. 要按顺序遍历一个序列,使用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类,可以直接继承,或者间接继承。
    实例:
  • python print dataframe 没有对齐_python

  • 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 类的方法

python print dataframe 没有对齐_实例化_02在类的内部,使用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 类属性与方法

  • 类的私有属性
  1. __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)  # 报错,实例不能访问私有变量
  • 类的方法
  1. 在类的内部,使用def关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数,self代表的是类的实例。
  2. self的名字并不是规定死的,也可以使用this,但是最好还是按照约定是用self
  • 类的私有方法
  1. __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内定义的静态方法,没有类似selfcls这样的特殊参数,和函数唯一的区别是:静态方法定义在类这个空间(类命名空间)中,而函数则定义在程序所在的空间(全局命名空间)中。
  • 静态方法需要使用@staticmethod修饰,示例:
@staticmethod
    def static_method():
  • 静态方法的调用,既可以使用类名,也可以使用类对象。