Skip to content

语法进阶

一、数据结构

1、列表

列表可以修改,而字符串和元组不能

方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在 Python 库参考手册中遇到这样的标记。

方法描述
list.append(x)尾插(a[len(a):] = [x])
list.extend(L)通过添加指定列表的所有元素来扩充列表(a[len(a):] = L)
list.insert(i, x)头差( a.insert(0, x) 会插入到整个列表之前)
list.remove(x)删除列表中第一个值为 x 的元素(没有x报错)
list.pop([i])从列表的指定位置移除元素,并将其返回。如果没有指定索引,a.pop()返回最后一个元素。元素随即从列表中被移除。
list.clear()清空(del a[:])
list.index(x)返回列表中第一个值为 x 的元素的索引(没有x报错)
list.count(x)返回 x 在列表中出现的次数
list.sort()对列表中的元素进行排序。
list.reverse()翻转列表
list.copy()返回列表的浅复制(a[:])

2、列表->堆栈

append() 方法:把一个元素添加到堆栈顶

不指定索引的 pop() 方法:把一个元素从堆栈顶释放出来

3、del 语句

使用 del 语句可以从一个列表中根据索引来删除一个元素,而不是值来删除元素

可以用 del 语句从列表中删除一个切割,或清空整个列表

python
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]

>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]

>>> del a[:]
>>> a
[]

4、遍历

1)字典的items()

items() :同时解读关键字和对应的值

python
info = {'name' : 'wmh', 'web' : 'rexhao.work'}
for k,v in info.items():
    print(k,v) 
# name wmh
# web rexhao.work

2)序列的enumerate()

enumerate():在序列中遍历时,同时得到索引位置和对应值

python
for i, v in enumerate(['rex', 'hao', 'work']):
    print(i, v)
# 0 rex
# 1 hao
# 2 work

3)同时遍历多个序列

python
>>> 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))
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.

4)反向遍历

python
>>> for i in reversed(range(1, 10, 2)):
...     print(i)

5)排序后遍历

sorted() :返回一个已排序的序列,并不修改原值

python
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print(f)
...
apple
banana
orange
pear

二、模块

1、import 语句

python
import module1[, module2[,... moduleN]

当解释器遇到 import 语句,如果模块在当前的搜索路径就会被导入

搜索路径是一个解释器会先进行搜索的所有目录的列表(搜索路径是由一系列目录名组成的,解释器就依次从这些目录中去寻找所引入的模块)

查看搜索路径:导入sys包、打印sys.path

sys.path的其中第一项是空串'':代表当前目录

2、from … import 语句

从模块中导入一个指定的部分到当前命名空间中

这个声明不会把整个fibo模块导入到当前的命名空间中,它只会将fibo里的fib函数引入进来

from … import *:把一个模块的所有内容全都导入到当前的命名空间

3、__name__属性

每个模块都有一个__name__属性,当其值是'__main__'时,表明该模块自身在运行,否则是被引入

4、dir() 函数

内置的函数 dir() 可以找到模块内定义的所有名称。返回一个字符串列表

5、包

包是一种管理 Python 模块命名空间的形式,采用"点模块名称"

目录只有包含一个叫做 __init__.py 的文件才会被认作是一个包

  1. 对于 from package import item ,对应的 item 可以是包里面的子模块(子包),或者包里面定义的函数,类或者变量。
  2. import 会首先把 item 当作一个包定义的名称,再试图按照一个模块去导入。没找到抛出 :exc:ImportError 异常。
  3. import item.subitem.subsubitem :除了最后一项,都必须是包,最后一项则可以是模块或者是包(但是不可以是类,函数或者变量)

三、输入输出

1、输出的值转成字符串

str(): 函数返回一个用户易读的表达形式。

repr(): 产生一个解释器易读的表达形式。

python
>>> s = 'Hello, rex'
>>> str(s)
'Hello, rex'
>>> repr(s)
"'Hello, rex'"

2、输出格式美化

str.format()使用

python
>>> print('{}网址:"{}!"'.format('blog', 'rexhao.work'))
blog网址: "rexhao.work"

# 括号中的数字用于指向传入对象在 format() 中的位置
>>> print('{0}{1}'.format('Google', 'wmh'))
Google 和 wmh
>>> print('{1}{0}'.format('Google', 'wmh'))
wmh 和 Google

# 使用了关键字参数
>>> print('{name}网址:"{web}!"'.format(name='blog', web='rexhao.work'))
blog网址: "rexhao.work"

# 可选项:和格式标识符可以跟着字段名,或者传入一个整数, 可以保证该域至少有这么多的宽度
>>> import math
>>> print('π = {0:.3f}。'.format(math.pi))
π =  3.142

3、旧式字符串格式化

% 操作符也可以实现字符串格式化。

类似于c中的printf

python
>>> import math
>>> print('常量 PI 的值近似为:%5.3f。' % math.pi)
常量 PI 的值近似为:3.142

4、读取键盘输入

python
str = input("请输入:");
print ("你输入的内容是: ", str)

四、File

1、open()概述

open() :方法用于打开一个文件,并返回文件对象。如果该文件无法被打开,会抛出 OSError

使用open()方法一定要保证关闭文件对象,即调用close()方法

python
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

2、open()参数说明

  • file: 必需,文件路径(相对或者绝对路径)。
  • mode: 可选,文件打开模式
  • buffering: 设置缓冲区
  • encoding: 一般使用utf8
  • errors: 报错级别
  • newline: 区分换行符
  • closefd: 传入的file参数类型
  • opener: 设置自定义开启器,开启器的返回值必须是一个打开的文件描述符。

3、mode 参数

| 模式 | 描述 | | : | :----------------------------------------------------------- | | t | 文本模式 (默认)。 | | x | 写模式,新建一个文件,如果该文件已存在则会报错。 | | b | 二进制模式。 | | + | 打开一个文件进行更新(可读可写)。 | | U | 通用换行模式(Python 3 不支持)。 | | r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 | | rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 | | r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 | | rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 | | w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | | wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 | | w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 | | wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 | | a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 | | ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 | | a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 | | ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |

默认为文本模式,如果要以二进制模式打开,加上 b

4、file对象方法

  • file.close():关闭文件。关闭后文件不能再进行读写操作
  • file.flush():刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。
  • file.fileno():返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。
  • file.isatty():如果文件连接到一个终端设备返回 True,否则返回 False。
  • file.read([size]):从文件读取指定的字节数,如果未给定或为负则读取所有。
  • file.readline([size]):读取整行,包括 "\n" 字符。
  • file.readlines([sizeint]):读取所有行并返回列表,若给
  • sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。
  • file.seek(offset[, whence]):移动文件读取指针到指定位
  • file.tell():返回文件当前位置
  • file.truncate([size]):从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 windows 系统下的换行代表2个字符大小
  • file.write(str):将字符串写入文件,返回的是写入的字符长度
  • file.writelines(sequence):向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。

五、异常

1、异常概述

即便 Python 程序的语法是正确的,在运行它的时候,也有可能发生错误。运行期检测到的错误被称为异常。

大多数的异常都不会被程序处理,都以错误信息的形式展现在控制台

2、异常处理

1)try/except

类似与javase的try...catch...

python
while True:
    try:
        x = int(input("请输入数字: "))
        break
    except ValueError:
        print("您输入的不是数字,请再次尝试输入!")

一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常,但最多只有一个分支会被执行

一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组

2)try/except...else

try/except 语句还有一个可选的else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后。

else 子句将在 try 子句没有发生任何异常的时候执行

3)try-finally

类似与java的try...catch...finally

finally 语句:无论是否发生异常都将执行的代码

4)抛出异常

Python 使用 raise 语句抛出一个指定的异常

python
raise [Exception [, args [, traceback]]]

raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)

3、自定义异常

通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承

大多数的异常的名字都以"Error"结尾,就跟标准的异常命名一样

六、面向对象

1、面向对象简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • **方法:**类中定义的函数。
  • **类变量:**类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • **数据成员:**类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • **方法重写:**如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • **局部变量:**定义在方法中的变量,只作用于当前实例的类。
  • **实例变量:**在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
  • **继承:**即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例:Dog是一个Animal)。
  • **实例化:**创建一个类的实例,类的具体对象。
  • **对象:**通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

2、类定义

python
class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

3、类对象

类对象支持两种操作:属性引用和实例化

属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name

类对象创建后,类命名空间中所有的命名都是有效属性名

__init__() 构造方法:类实例化时会自动调用

4、类方法

类的方法与普通的函数只有一个特别的区别:必须有一个额外的第一个参数名称,按照惯例它的名称是 self

python
class people:
    name = ''
    age = 0
    #定义构造方法
    def __init__(self,n,a):
        self.name = n
        self.age = a
    def speak(self):
        print("%s:9%d 岁。" %(self.name,self.age))
 
# 实例化类
p = people('wmh',10)
p.speak()

5、继承

Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义

子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。

BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用

python
class DerivedClassName(modname.BaseClassName):
python
#类定义
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))
 
 
 
s = student('ken',10,60,3)
s.speak()

6、多继承

Python同样有限的支持多继承形式

python
class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

需要注意:圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索(方法在子类中未找到时,从左到右查找父类中是否包含方法)

7、方法重写

super():用于调用父类(超类)的一个方法

python
class Parent:        # 定义父类
   def myMethod(self):
      print ('调用父类方法')
 
class Child(Parent): # 定义子类
   def myMethod(self):
      print ('调用子类方法')
 
c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法

8、类的私有

__private_attrs:私有变量,两个下划线开头,只能在类中使用( self.__private_attrs

__private_method:私有方法,两个下划线开头,只能在类的内部调用 (self.__private_methods

9、运算符重载

Python同样支持运算符重载,我们可以对类的专有方法进行重载

  • __init__ :构造函数,在生成对象时调用
  • __del__ :析构函数,释放对象时使用
  • __repr__:打印,转换
  • __setitem__:按照索引赋值
  • __getitem__:按照索引获取值
  • __len__:获得长度
  • __cmp__:比较运算
  • __call__:函数调用
  • __add__:加运算
  • __sub__:减运算
  • __mul__:乘运算
  • __truediv__:除运算
  • __mod__:求余运算
  • __pow__:乘方
python
class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b
 
   def __str__(self):
      return 'Vector (%d, %d)' % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)
 
v1 = Vector(1,3)
v2 = Vector(2,4)
print (v1 + v2)

# Vector(3, 7)

七、命名空间和作用域

1、命名空间

  • 内置名称(built-in names): Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
  • 全局名称(global names):模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部名称(local names):函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间。

命名空间的生命周期:取决于对象的作用域,若对象执行完成,该命名空间的生命周期就结束

2、作用域

规则顺序: L –> E –> G –> B

  • L(Local):最内层,包含局部变量,比如一个函数/方法内部。
  • E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。
  • G(Global):当前脚本的最外层,比如当前模块的全局变量。
  • B(Built-in): 包含了内建的变量/关键字等,最后被搜索。

if/elif/else/、try/except、for/while等是不会引入新的作用域的,这些语句内定义的变量,外部也可以访问

3、全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

global关键字:修改全局变量

python
num = 1
def fun1():
    global num  # 需要使用 global 关键字声明
    print(num) 	# 1
    num = 123
    print(num)	# 123
fun1()
print(num)		# 123

nonlocal关键字:声明外部嵌套函数内的变量(类似于c中的static,函数调用完但是变量不会消失)

Released under the MIT License.