ixxmu / mp_duty

抓取网络文章到github issues保存
https://archives.duty-machine.now.sh/
89 stars 24 forks source link

Python应该要会一点吧 #3112

Closed ixxmu closed 1 year ago

ixxmu commented 1 year ago

https://mp.weixin.qq.com/s/2l_9CHxJGGHWw0zXV34y1A

ixxmu commented 1 year ago

Python应该要会一点吧 by 繁尘的bio小本本

近期看了一下《Python编程 从入门到实践》这本书,然后写了一些笔记,和大家分享一下。

Part1PyCharm 编辑器

https://www.jetbrains.com/pycharm/download/#section=windows

一个好的编辑器能让编程变得更加简单、方便一点,我用的是PyCharm,感觉还挺好用的,Community版本可在上图网址中免费下载、使用。

Part2基础知识

本文内容主要针对于Python 3。

1起步

查看帮助文档

help(print#如查看print函数的使用方法。
----------------------------
Help on built-in function print in module builtins:
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

2变量和简单数据类型

变量的命名和使用

  1. 变量名只能包含字母、数字和下划线。
  2. 变量名不能包含空格,但可使用下划线来分隔其中的单词。
  3. 不要将Python关键字和函数名用作变量名。
  4. 变量名应既简短又具有描述性
  5. 慎用大写字母I和O,因为它们可能被人错看成数字1和0。
Python 关键字
Python 内置函数

使用变量时避免命名错误

hello_world.py #文件名
----------------------------
message = "Hello Python Crash Course reader!" 
print(mesage) #Python运行代码
----------------------------
Traceback (most recent call last): 
 File "hello_world.py", line 2, in <module> #文件“hello_world.py”中第二行有问题
  print(mesage) #报错代码
NameError: name 'mesage' is not defined #具体问题:名为“mesage”的对象未找到。

字符串

使用方法修改字符串的大小写

name = "Ada Lovelace" 
print(name.upper()) #将字符串改为全部大写
print(name.lower()) #将字符串改为全部小写
----------------------------
ADA LOVELACE #上述代码输出结果
ada lovelace

合并(拼接)字符串

first_name = "ada" 
last_name = "lovelace" 
full_name = first_name + " " + last_name #Python使用加号(+)来合并字符串,这种方法称为拼接。
print(full_name)
----------------------------
ada lovelace 

转义字符对照表

转义字符意义
\a响铃(BEL)
\b退格(BS),将当前位置移到前一列
\f换页(FF),将当前位置移到下页开头
\n换行(LF),将当前位置移到下一行开头
\r回车(CR),将当前位置移到本行开头
\t水平制表(HT)(跳到下一个TAB位置)
\v垂直制表(VT)
\'代表一个单引号
\"代表一个双引号字符
\\代表一个反斜线字符'\'
\0空字符(NUL)
\ddd1到3位八进制数所代表的任意字符
\xhh十六进制所代表的任意字符
表格中的部分转义字符在Python中不适用。
https://www.cnblogs.com/tabkey9/p/15930390.html
print("Languages:\nPython\nC\nJavaScript")#举例说明
----------------------------
Languages: 
Python 

JavaScript

删除空白

favorite_language = ' python '
favorite_language.rstrip() #删除末尾的空格
favorite_language.lstrip() #删除开头的空格
favorite_language.strip() #删除两端的空格
----------------------------
' python'
'python '
'python'

数字

#基本运算符号:加(+)减(-)乘(*)除(/)
#空格不影响Python计算表达式的方式。
0.2 + 0.1 #在处理部分浮点数会出现如下情况
3 * 0.1 
----------------------------
0.30000000000000004 #原因在与十进制到二进制的转换导致的精度问题
0.30000000000000004
round(0.2+0.1,2) #可用该函数解决此问题
----------------------------
0.3

函数 str()

age = 23 #数值型变量不能和字符型变量合并
type(age)
message = "Happy " + str(age) + "rd Birthday!" #需用str()将数值型变量转换为字符串
print(message)
#int() 将对象转换为整数
#float() 将对象转换为小数(浮点数)
----------------------------
<class 'int'>
Happy 23rd Birthday!

Python 之禅

import this #编写优秀Python代码的指导原则
----------------------------
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
... #在此省略,完整内容可在Python中输入上述代码查看。
If the implementation is hard to explain, it's a bad idea.

3列表简介

bicycles = ['trek''cannondale''redline''specialized']
print(bicycles) #在Python中,用方括号([])来表示列表,并用逗号来分隔其中的元素。
----------------------------
['trek''cannondale''redline''specialized']

访问列表元素

bicycles = ['trek''cannondale''redline''specialized']
print(bicycles[1]) #在Python中,第一个列表元素的索引为0,而不是1
print(bicycles[3])
print(bicycles[-1]) #通过将索引指定为-1,可让Python返回最后一个列表元素
----------------------------
cannondale 
specialized
specialized

修改列表元素

motorcycles = ['honda''yamaha''suzuki'
print(motorcycles) 
motorcycles[0] = 'ducati' 
print(motorcycles)
----------------------------
['honda''yamaha''suzuki'
['ducati''yamaha''suzuki']

在列表中添加元素

motorcycles = ['honda''yamaha''suzuki'
print(motorcycles) 
motorcycles.append('ducati'#将元素附加到列表末尾
print(motorcycles)
motorcycles.insert(0, 'ducati'#在索引0处添加空间,并将值'ducati'存储到这个地方
print(motorcycles)
----------------------------
['honda''yamaha''suzuki'
['honda''yamaha''suzuki''ducati']
['ducati''honda''yamaha''suzuki''ducati']

从列表中删除元素

motorcycles = ['honda''yamaha''suzuki'
print(motorcycles)
del motorcycles[1] #删除索引为1的元素,删除后无法再次访问该元素。
print(motorcycles)
popped_motorcycle = motorcycles.pop(1) #删除索引为1的元素,并将该元素存储在新变量中
#pop()括号内默认参数为-1
print(motorcycles) 
print(popped_motorcycle) 
----------------------------
['honda''yamaha''suzuki']
['honda''suzuki']
['honda']
suzuki
motorcycles = ['honda''yamaha''suzuki''ducati''honda'
print(motorcycles) 
motorcycles.remove('honda'#根据值删除元素
print(motorcycles) #但是,方法remove()只删除第一个指定的值
----------------------------
['honda''yamaha''suzuki''ducati''honda']
['yamaha''suzuki''ducati''honda']

组织列表

cars = ['bmw''audi''toyota''subaru'
cars.sort() #按字母顺序排列
print(cars)
cars.sort(reverse=True) #按与字母顺序相反的顺序排列
print(cars)
----------------------------
['audi''bmw''subaru''toyota']
['toyota''subaru''bmw''audi']
cars = ['bmw''audi''toyota''subaru'
print(cars) 
cars.reverse() #反转列表元素的排列顺序
print(cars)
----------------------------
['bmw''audi''toyota''subaru']
['subaru''toyota''audi''bmw']
cars = ['bmw''audi''toyota''subaru']
len(cars) #确定列表的长度
----------------------------
4

4操作列表

magicians = ['alice''david''carolina'
for magician in magicians: #for循环。注意,冒号不能遗漏
  print(magician) 
#从列表magicians中取出一个名字,并将其存储在变量magician中,并将其打印出来
print("Thank you, everyone. That was a great magic show!")
#for循环后面,缩进的代码才属于循环内容,会重复执行
----------------------------
alice 
david 
carolina
Thank you, everyone. That was a great magic show!

创建数值列表

numbers = list(range(1,6)) #创建数字1~5,并以list的格式储存在变量”numbers“中
print(numbers)
----------------------------
[1, 2, 3, 4, 5] #差一行为
even_numbers = list(range(2,11,2)) #从2开始数,然后不断地加2,直到达到或超过终值
print(even_numbers)
----------------------------
[2, 4, 6, 8, 10]
digits = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
print(min(digits)) #对数字列表执行简单的统计计算
print(max(digits))
print(sum(digits))
----------------------------
0
9
45
squares = [value**2 for value in range(1,11)] #列表解析
#指定一个左方括号,并定义一个表达式,本例中,表达式为value**2
#value**2,表示计算value的平方值
#接下来,编写一个for循环,用于给表达式提供值,再加上右方括号
#这里的for语句末尾没有冒号
print(squares)
----------------------------
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

使用列表的一部分

#处理列表的部分元素——Python称之为切片
players = ['charles''martina''michael''florence''eli'
print(players[1:4]) #提取列表的第2~4个元素
print(players[:4]) #没有指定起始索引,Python将自动从列表开头开始
print(players[2:]) #提取从第3个元素到列表末尾的所有元素
print(players[-3:]) #提取最后3个元素
----------------------------
['martina''michael''florence']
['charles''martina''michael''florence']
['michael''florence''eli']
['michael''florence''eli']

复制列表

players = ['charles''martina''michael''florence''eli']
my_players = players[:] #正确做法
my_foods = ['pizza''falafel''carrot cake'
friend_foods = my_foods #错误做法
#这里将my_foods赋给friend_foods,而不是将my_foods的副本存储到friend_foods
my_foods.append('cannoli')
friend_foods.append('ice cream')
print(my_foods)
print(friend_foods)
#因此这两个变量都指向同一个列表
----------------------------
['pizza''falafel''carrot cake''cannoli''ice cream']
['pizza''falafel''carrot cake''cannoli''ice cream']

元组

#Python将不能修改的值称为不可变的,而不可变的列表被称为元组
dimensions = (200, 50) #元组看起来犹如列表,但使用圆括号来标识
print(dimensions[0]) 
dimensions[0] = 250 #尝试修改元组dimensions中的一个元素
----------------------------
200
Traceback (most recent call last): #试图修改元组的操作是被禁止的
 File "dimensions.py", line 3, in <module> 
 dimensions[0] = 250 
TypeError: 'tuple' object does not support item assignment

修改元组变量

dimensions = (200, 50)
for dimension in dimensions: 
  print(dimension) 
dimensions = (400, 100) #重新定义整个元组
for dimension in dimensions: 
  print(dimension)
----------------------------
200
50
400
100

设置代码格式

PEP 8(Python Enhancement Proposal 8)向Python程序员提供了代码格式设置指南,一般编辑器里都有相关的设置,如Pycharm,一个TAB等于4个空格(可以在设置里修改)(tab:向右缩进)(shift + tab:向左缩进)、行长一般不超过80字符(上图的那条竖线)、还有一些其他问题Pycharm也在代码检查的时候给标记了出来(只要不是红色,代码就没有语法问题)。

5if语句

cars = ['audi''bmw''subaru''toyota'
for car in cars: 
  if car == 'bmw'
    print(car.upper()) 
  else
    print(car.title())
#检查当前的汽车名是否是'bmw'。如果是,就以全大写的方式打印它;
#否则就以首字母大写的方式打印
----------------------------
Audi 
BMW 
Subaru 
Toyota
条件语句中的逻辑符:
== 是否等于   != 是否不等于
< 是否小于   > 是否大于 
<= 是否小于等于   >=是否大于等于
布尔表达式:结果要么为True,要么为False

检查多个条件

age_0 = 22 
age_1 = 18 
age_0 >= 21 and age_1 >= 21
age_0 >= 21 or age_1 >= 21
----------------------------
False
True

检查特定值是否包含在列表中

requested_toppings = ['mushrooms''onions''pineapple'
'mushrooms' in requested_toppings #是否包含
'mushrooms' not in requested_toppings #是否不包含
----------------------------
True
False

if-elif-else 结构

age = 12 
if age < 4: #年龄小于4岁免门票
  price = 0 
elif age < 18: #4-18岁半价
  price = 5 
elif age < 65: #18-65岁全票
  price = 10 
else#其他年龄组半价
  price = 5 
print("Your admission cost is $" + str(price) + ".")
----------------------------
Your admission cost is $5.

省略 else 代码块

age = 12 
if age < 4: 
 price = 0 
elif age < 18: 
 price = 5 
elif age < 65: 
 price = 10 
elif age >= 65: 
 price = 5 
print("Your admission cost is $" + str(price) + ".")
----------------------------
Your admission cost is $5.
#else是一条包罗万象的语句,只要不满足任何if或elif中的条件测试,
#其中的代码就会执行,这可能会引入无效甚至恶意的数据
#如果知道最终要测试的条件,应考虑使用一个elif代码块来代替else代码块

确定列表不是空的

requested_toppings = [] #创建空列表
if requested_toppings: #如果requested_toppings不为空,则运行以下代码
  for requested_topping in requested_toppings: 
    print("Adding " + requested_topping + "."
  print("\nFinished making your pizza!"
else#否则运行以下代码
  print("Are you sure you want a plain pizza?")
----------------------------
Are you sure you want a plain pizza?

6字典

#在Python中,字典是一系列键—值对
#每个键都与一个值相关联,你可以使用键来访问与之相关联的值
#事实上,可将任何Python对象用作字典中的值
alien_0 = {'color''green''points': 5} 
print(alien_0['color']) #访问字典中的值
print(alien_0['points'])
alien_0['x_position'] = 0 #添加键—值对
print(alien_0)
----------------------------
green
5
{'color''green''points': 5, 'x_position': 0}
alien_0 = {'color''green''points': 5} 
alien_0['color'] = 'yellow' #修改字典中的值
print(alien_0)
del alien_0['points'#删除键—值对
print(alien_0)
----------------------------
{'color''yellow''points': 5}
{'color''yellow'}

遍历字典

user_0 = { 
 'username''efermi'
 'first''enrico'
 'last''fermi'
 } 
#使用for循环,声明两个变量,用于存储键—值对中的键和值
for key, value in user_0.items(): #items()返回一个键—值对列表
  print("\nKey: " + key) 
  print("Value: " + value)
----------------------------

Key: username
Value: efermi

Key: first
Value: enrico

Key: last
Value: fermi
favorite_languages = { 
 'jen''python'
 'sarah''c'
 'edward''ruby'
 'phil''python'
 }
for name in favorite_languages.keys(): #keys()提取字典中的所有键
  print(name.title())
#省略keys(),输出结果不变
for language in favorite_languages.values(): #values()提取字典中的所有值
  print(language.title())
----------------------------
Jen
Sarah
Edward
Phil
Python
C
Ruby
Python
favorite_languages = { 
 'jen''python'
 'sarah''c'
 'edward''ruby'
 'phil''python'
 } 
for language in set(favorite_languages.values()): #剔除重复项
  print(language.title())
#集合(set)类似于列表,但每个元素都必须是独一无二的
----------------------------
Python
Ruby
C

嵌套

#将一系列字典存储在列表中,或将列表作为值存储在字典中,这称为嵌套
alien_0 = {'color''green''points': 5} 
alien_1 = {'color''yellow''points': 10} 
alien_2 = {'color''red''points': 15} 
aliens = [alien_0, alien_1, alien_2] #将字典储存在列表中
for alien in aliens: 
  print(alien)
----------------------------
{'color''green''points': 5} 
{'color''yellow''points': 10} 
{'color''red''points': 15}

favorite_languages = { #将列表储存在字典中
 'jen': ['python''ruby'], #一个键关联到多个值
 'sarah': ['c'], 
 'edward': ['ruby''go'], 
 'phil': ['python''haskell'], 
 }
for name, languages in favorite_languages.items(): 
  print("\n" + name.title() + "'s favorite languages are:")
  for language in languages: 
    print("\t" + language.title())
#在遍历该字典的for循环中,再使用一个for循环来遍历与被调查者相关联的语言列表
#列表和字典的嵌套层级不应太多。
#如果嵌套层级比前面的示例多得多,很可能有更简单的解决问题的方案
----------------------------

Jen's favorite languages are:
 Python
 Ruby
  
Sarah'
s favorite languages are:
 C
  
Edward's favorite languages are:
 Ruby
 Go
  
Phil'
s favorite languages are:
 Python
 Haskell
users = { #在字典中储存字典
 'aeinstein': { 
 'first''albert'
 'last''einstein'
 'location''princeton'
 }, 
 'mcurie': { 
 'first''marie'
 'last''curie'
 'location''paris'
 }, 
 }

7用户输入和while循环

函数input()的工作原理

#input()让程序暂停运行,等待用户输入一些文本。
#获取用户输入后,Python将其存储在一个变量中,以方便你使用
prompt = "If you tell us who you are, we can personalize the messages you see." 
prompt += "\nWhat is your first name? " 
name = input(prompt) 
print("\nHello, " + name + "!")
#运算符+=在存储在prompt中的字符串末尾附加一个字符串
----------------------------
If you tell us who you are, we can personalize the messages you see.
What is your first name? >? fanchen

Hello, fanchen!
age = input("How old are you? "#input()会将用户输入解读为字符串
type(age) #查看age类型
age = int(age) #将字符串转换为整型
age >= 18
----------------------------
How old are you? >? 21
<class 'int'>
True

求模运算符

number = input("Enter a number, and I'll tell you if it's even or odd: "
number = int(number) 
if number % 2 == 0: #它将两个数相除并返回余数
 print("\nThe number " + str(number) + " is even."
else
 print("\nThe number " + str(number) + " is odd.")
#如果一个数可被另一个数整除,余数就为0,因此求模运算符将返回0
#你可利用这一点来判断一个数是奇数还是偶数
----------------------------
Enter a number, and I'll tell you if it's even or odd: >? 42
The number 42 is even.

while 循环简介

current_number = 1 
while current_number <= 5: #只要current_number小于或等于5,就接着运行这个循环
  print(current_number) 
  current_number += 1
----------------------------
1
2
3
4
5
prompt = "\nTell me something, and I will repeat it back to you:" 
prompt += "\nEnter 'quit' to end the program. "
active = True #这个变量被称为标志,用于判断整个程序是否处于活动状态
while active: 
  message = input(prompt) 
  if message == 'quit'
    active = False #当标志的值为False时,程序停止运行
  else
    print(message)

使用 break 退出循环

prompt = "\nPlease enter the name of a city you have visited:" 
prompt += "\n(Enter 'quit' when you are finished.) " 
while True: 
  city = input(prompt) 
  if city == 'quit'
    break #执行break语句,使Python退出循环
  else
    print("I'd love to go to " + city.title() + "!")

在循环中使用 continue

current_number = 0 
while current_number < 10: 
  current_number += 1 
  if current_number % 2 == 0: 
    continue #不再执行余下的代码,并返回到循环开头
  print(current_number)
----------------------------
1
3
5
7
9

避免无限循环

# 这个循环将没完没了地运行!
x = 1 
while x <= 5: 
 print(x)
----------------------------
#按Ctrl + C,终止进程
Traceback (most recent call last):
  File "<input>", line 3, in <module>
KeyboardInterrupt
#也可关闭显示程序输出的控制台(Console)来解决此问题
#关闭整个Python来解决该问题当然也是可以的。
#不过,第三种方法不太好用,毕竟重新打开Python花费的时间比前两种方法多

8函数

def greet_user(): #用关键字def来定义一个函数
  """显示简单的问候语""" #文档字符串(docstring)的注释
  print("Hello!"#def后的所有缩进行构成了函数体
greet_user() #函数调用
----------------------------
Hello!

向函数传递信息

def greet_user(username): #通过添加username,就可让函数接受你给username指定的任何值
  """显示简单的问候语"""
  print("Hello, " + username.title() + "!"
greet_user('jesse')
#变量username是一个形参——函数完成其工作所需的一项信息。
#值'jesse'是一个实参——调用函数时传递给函数的信息。
----------------------------
Hello, Jesse!

传递实参

#调用函数时,基于实参顺序的关联方式被称为位置实参
def describe_pet(animal_type, pet_name): 
  """显示宠物的信息""" 
  print("\nI have a " + animal_type + "."
  print("My " + animal_type + "'s name is " + pet_name.title() + "."
describe_pet('hamster''harry')
#实参'hamster'存储在形参animal_type中,
#实参'harry'存储在形参pet_name中
----------------------------
I have a hamster. 
My hamster's name is Harry.

关键字实参

def describe_pet(animal_type, pet_name): 
  """显示宠物的信息""" 
  print("\nI have a " + animal_type + "."
  print("My " + animal_type + "'s name is " + pet_name.title() + "."
describe_pet(animal_type='hamster', pet_name='harry')
#传递给函数的名称—值对,无需考虑函数调用中的实参顺序

默认值

#在调用函数中给形参提供了实参时,Python将使用指定的实参值;
#否则,将使用形参的默认值
def describe_pet(pet_name, animal_type='dog'): 
  """显示宠物的信息""" 
  print("\nI have a " + animal_type + "."
  print("My " + animal_type + "'s name is " + pet_name.title() + ".")
describe_pet(pet_name='willie')
#Python依然将这个实参视为位置实参
#所以在函数定义时,没有默认值的参数应放在设置了默认值的参数之前
----------------------------
I have a dog. 
My dog's name is Willie.

返回简单值

def get_formatted_name(first_name, last_name): 
  """返回整洁的姓名""" 
  full_name = first_name + ' ' + last_name 
  return full_name.title() #return将结果返回到函数调用行
musician = get_formatted_name('jimi''hendrix'
print(musician)
----------------------------
Jimi Hendrix

让实参变成可选的

def get_formatted_name(first_name, last_name, middle_name=''): 
  """返回整洁的姓名""" 
#检查是否提供了中间名
  if middle_name: #Python将非空字符串解读为True
    full_name = first_name + ' ' + middle_name + ' ' + last_name 
  else
    full_name = first_name + ' ' + last_name 
  return full_name.title() 
musician = get_formatted_name('jimi''hendrix'
print(musician) 
musician = get_formatted_name('john''hooker''lee'
print(musician)
----------------------------
Jimi Hendrix 
John Lee Hooker

每个函数都应只负责一项具体的工作;在一个函数中可以调用另一个函数,这有助于将复杂的任务划分成一系列的步骤。

可以用切片表示法[:]创建列表的副本,虽然向函数传递列表的副本可保留原始列表的内容,但除非有充分的理由需要传递副本,否则还是应该将原始列表传递给函数,因为让函数使用现成列表可避免花时间和内存创建副本,从而提高效率,在处理大型列表时尤其如此。

传递任意数量的实参

#形参名*toppings中的星号让Python创建一个名为toppings的空元组,
#并将收到的所有值都封装到这个元组中
def make_pizza(*toppings): 
  """打印顾客点的所有配料""" 
  print(toppings) 
make_pizza('pepperoni'
make_pizza('mushrooms''green peppers''extra cheese')
----------------------------
('pepperoni',) 
('mushrooms''green peppers''extra cheese')

结合使用位置实参和任意数量实参

def make_pizza(size, *toppings):
  """概述要制作的比萨"""
  print("\nMaking a " + str(size) +
        "-inch pizza with the following toppings:")
  for topping in toppings:
      print("- " + topping)
make_pizza(16, 'pepperoni')
make_pizza(12, 'mushrooms''green peppers''extra cheese')
#如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量实参的形参放在最后。
#Python先匹配位置实参和关键字实参,再将余下的实参都收集到最后一个形参中
----------------------------

Making a 16-inch pizza with the following toppings:
- pepperoni

Making a 12-inch pizza with the following toppings:
- mushrooms
- green peppers
- extra cheese

使用任意数量的关键字实参

#形参**user_info中的两个星号让Python创建一个名为user_info的空字典,
#并将收到的所有名称—值对都封装到这个字典中
def build_profile(first, last, **user_info): 
  """创建一个字典,其中包含我们知道的有关用户的一切""" 
  profile = {} 
  profile['first_name'] = first 
  profile['last_name'] = last 
  for key, value in user_info.items():
    profile[key] = value 
  return profile 
user_profile = build_profile('albert''einstein'
                              location='princeton'
                              field='physics'
print(user_profile)
----------------------------
{'first_name''albert''last_name''einstein''location''princeton''field''physics'}

将函数存储在模块中

要让函数是可导入的,得先创建模块。模块是扩展名为.py的文件,包含要导入到程序中的代码。

pizza.py #文件名
----------------------------
def make_pizza(size, *toppings): 
  """概述要制作的比萨""" 
  print("\nMaking a " + str(size) + 
        "-inch pizza with the following toppings:"
  for topping in toppings: 
    print("- " + topping)

接下来,我们就可以在pizza.py所在的目录中创建另一个文件,导入刚创建的模块,再调用make_pizza()

import pizza 
pizza.make_pizza(16, 'pepperoni')
----------------------------

Making a 16-inch pizza with the following toppings:
- pepperoni

导入特定的函数

from module_name import function_name #导入模块中的特定函数
from module_name import function_0, function_1, function_2
#从模块中导入任意数量的函数

使用 as 给函数指定别名

#关键字as将函数重命名为你提供的别名
from pizza import make_pizza as mp 
mp(16, 'pepperoni')

使用 as 给模块指定别名

import pizza as p #给模块指定别名
p.make_pizza(16, 'pepperoni')

导入模块中的所有函数

from pizza import * 
make_pizza(16, 'pepperoni')
#这样可能遇到多个名称相同的函数或变量,进而覆盖函数
#这种导入方法不建议使用

函数编写指南

  1. 应给函数指定描述性名称,且只在其中使用小写字母和下划线。
  2. 给形参指定默认值时,等号两边不要有空格:def function_name(parameter_0, parameter_1='default value')。对于函数调用中的关键字实参,也应遵循这种约定。
  3. 建议代码行的长度不要超过79字符,这样方便查看。
  4. 如果程序或模块包含多个函数,可使用两个空行将相邻的函数分开,这样将更容易知道前一个函数在什么地方结束,下一个函数从什么地方开始。
  5. 所有的import语句都应放在文件开头,唯一例外的情形是,在文件开头使用了注释来描述整个程序。

在使用编辑器编写代码的时候,大部分编辑器都会给出相应的建议提示。

9

编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。根据类来创建对象被称为实例化,这让你能够使用类的实例。

创建和使用类

class Dog(): #创建 Dog 类
  """一次模拟小狗的简单尝试""" #类中的函数称为方法
#__init__()是一个特殊的方法,每当你根据Dog类创建新实例时,Python都会自动运行它
  def __init__(self, name, age): #self会自动传递,我们不需要传递它
    """初始化属性name和age""" 
    self.name = name 
    self.age = age 
  def sit(self): 
    """模拟小狗被命令时蹲下""" 
    print(self.name.title() + " is now sitting."
  def roll_over(self): 
    """模拟小狗被命令时打滚""" 
    print(self.name.title() + " rolled over!")
#以self为前缀的变量都可供类中的所有方法使用
----------------------------

根据类创建实例

#使用前一个示例中编写的Dog类
my_dog = Dog('willie', 6) #创建实例
my_dog.name #使用句点表示法访问实例的属性
my_dog.sit() #调用方法
#可按需求根据一个类创建任意数量的实例,
#条件是将每个实例都存储在不同的变量中,或占用列表或字典的不同位置
----------------------------
'willie'
Willie is now sitting.

继承

class Car():
  """一次模拟汽车的简单尝试"""
  def __init__(self, make, model, year): #初始化
    self.make = make
    self.model = model
    self.year = year
    self.odometer_reading = 0 #设置里程表默认值
  def get_descriptive_name(self): #描述车的基本信息
    long_name = str(self.year) + ' ' + self.make + ' ' + self.model
    return long_name.title()
  def read_odometer(self): #获取车的里程表
    print("This car has " + str(self.odometer_reading) + " miles on it.")
  def update_odometer(self, mileage): #更新里程表
    if mileage >= self.odometer_reading:
      self.odometer_reading = mileage
    else#设置里程表不能往下调
      print("You can't roll back an odometer!")
  def increment_odometer(self, miles): #将里程表读数增加指定的量
    self.odometer_reading += miles

class ElectricCar(Car): 
  """电动汽车的独特之处""" 
  def __init__(self, make, model, year): 
    """初始化父类的属性,再初始化电动汽车特有的属性""" 
#特殊函数super()帮助Python将父类和子类关联起来
    super().__init__(make, model, year) 
#这行代码让Python调用ElectricCar的父类的方法__init__(),
#让ElectricCar实例包含父类的所有属性。
#父类也称为超类(superclass),名称super因此而得名
    self.battery_size = 70 #创建电动汽车特有的属性
  def describe_battery(self): 
    """打印一条描述电瓶容量的消息""" 
    print("This car has a " + str(self.battery_size) + "-kWh battery.")
    
my_tesla = ElectricCar('tesla''model s', 2016) 
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
----------------------------
2016 Tesla Model S
This car has a 70-kWh battery.
tip:

在PyCharm里(这个技巧应该是通用的),如果觉得代码太长,不想看某一段可以按Ctrl+减号(-)进行代码收缩。若想将代码展开可用鼠标点击代码收缩处或按Ctrl+加号(+)。效果如下:

class Car():... #此处为收缩内容

重写父类的方法

对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

导入类

导入类的方法与前文导入函数的方法基本一致。

Python 标准库

Python标准库是一组模块,安装的Python都包含它。无需额外安装此库,只需在程序开头包含一条简单的import语句便可使用。

类编码风格

  1. 类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
  2. 对于每个类,都应紧跟在类定义后面包含一个简要地描述类的功能的文档字符串。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
  3. 在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
  4. 需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import语句,再添加一个空行,然后编写导入你自己编写的模块的import语句。

10文件和异常

从文件中读取数据

pi_digits.txt 
----------------------------
3.1415926535 
 8979323846 
 2643383279
with open('pi_digits.txt') as file_object: #确保和该文件在同一路径下
  contents = file_object.read() #读取文件
  print(contents)
#用完文件可以调用close()来关闭文件,防止在某些情况下会产生一些错误。
#当然,如果未写close()语句,Python会在合适的时候自动将其关闭。
----------------------------
3.1415926535
  8979323846
  2643383279

文件路径

#如果想打开的文件和运行的程序不在同一路径下,
#可使用绝对路径读取文件
file_path = 'C:/Users/ehmatthes/other_files/text_files/filename.txt' 
with open(file_path) as file_object:
#建议使用斜杠(/)而不是反斜杠(\)来查找文件(包括windows系统)
#还有一种方法,修改当前的工作路径,使之与要打开的文件保持一致
import os #导入os库
print(os.getcwd()) #查看当前工作路径
os.chdir('C:/Users/ASUS/Desktop/venv'#修改工作路径

逐行读取

filename = 'pi_digits.txt' 
with open(filename) as file_object: 
  for line in file_object: #使用for循环以每次一行的方式检查文件
    print(line)
----------------------------
3.1415926535

  8979323846

  2643383279
#可使用print(line.rstrip())将每行末尾的换行符(\n)去掉
#另一种逐行读取文件的方法
filename = 'pi_digits.txt'
with open(filename) as file_object:
  lines = file_object.readlines() #创建一个包含文件各行内容的列表
for line in lines:
  print(line.rstrip())
#读取文本文件时,Python将其中的所有文本都解读为字符串

写入文件

filename = 'programming.txt' 
with open(filename, 'w') as file_object: 
#第二个实参('w')告诉Python,我们要以写入模式打开这个文件
  file_object.write("I love programming.\n"
  file_object.write("I love creating new games.\n"#写入多行
help(open)
#查看open()的帮助文档
----------------------------
Help on built-in function open in module io:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
    Open file and return a stream.  Raise OSError upon failure.
...
    ========= ===============================================================
    Character Meaning
    --------- ---------------------------------------------------------------
    'r'       open for reading (default)
    'w'       open for writing, truncating the file first
    'x'       create a new file and open it for writing
    'a'       open for writing, appending to the end of the file if it exists
    'b'       binary mode
    't'       text mode (default)
    '+'       open a disk file for updating (reading and writing)
    'U'       universal newline mode (deprecated)
    ========= ===============================================================
...

异常

使用 try-except 代码块

try: 
  print(5/0) #错误代码
except ZeroDivisionError: #ZeroDivisionError是一个异常对象
  print("You can't divide by zero!")
#如果try代码块中的代码运行起来没有问题,Python将跳过except代码块;
#如果try代码块中的代码导致了错误,Python将查找这样的except代码块,
#并运行其中的代码,即其中指定的错误与引发的错误相同。
----------------------------
You can't divide by zero!

分析文本

filename = 'alice.txt' 
try: 
  with open(filename) as f_obj: 
    contents = f_obj.read() 
except FileNotFoundError: 
  msg = "Sorry, the file " + filename + " does not exist." 
  print(msg) 
else
  #计算文件大致包含多少个单词 
  words = contents.split() #根据一个字符串创建一个单词列表
  num_words = len(words) #确定列表的长度
  print("The file " + filename + " has about " + str(num_words) + " words."

存储数据

用户关闭程序时,你几乎总是要保存他们提供的信息;一种简单的方式是使用模块json来存储数据。

JSON(JavaScript Object Notation)格式最初是为JavaScript开发的,但随后成了一种常见格式,被包括Python在内的众多语言采用。

#存储数据
import json #导入模块json
numbers = [2, 3, 5, 7, 11, 13] 
filename = 'numbers.json' 
with open(filename, 'w') as f_obj: #以写入模式打开文件
  json.dump(numbers, f_obj) #将numbers存储到numbers.json中
#读取数据
mport json 
filename = 'numbers.json' 
with open(filename) as f_obj: #默认参数为读取模式
numbers = json.load(f_obj) #读取文件

11测试代码

编写函数或类时,还可为其编写测试。通过测试,可确定代码面对各种输入都能够按要求的那样工作。在程序中添加新代码时,你也可以对其进行测试,确认它们不会破坏程序既有的行为。

Python标准库中的模块unittest提供了代码测试工具。单元测试用于核实函数的某个方面没有问题;测试用例是一组单元测试,这些单元测试一起核实函数在各种情形下的行为都符合要求。

良好的测试用例考虑到了函数可能收到的各种输入,包含针对所有这些情形的测试。全覆盖式测试用例包含一整套单元测试,涵盖了各种可能的函数使用方式。对于大型项目,要实现全覆盖可能很难。通常,最初只要针对代码的重要行为编写测试即可,等项目被广泛使用时再考虑全覆盖。

测试函数

test_name_ function.py 
----------------------------
#运行test_name_function.py时,所有以test_打头的方法都将自动运行
import unittest 
from name_function import get_formatted_name 
class NamesTestCase(unittest.TestCase): 
#创建了名为NamesTestCase的类,用来继承unittest.TestCase类
  """测试name_function.py""" 
  def test_first_last_name(self): 
    """能够正确地处理像Janis Joplin这样的姓名吗?""" 
    formatted_name = get_formatted_name('janis''joplin'
    self.assertEqual(formatted_name, 'Janis Joplin'
#self.assertEqual():是一种断言方法,用来核实得到的结果是否与期望的结果一致
#本行代码意思:将formatted_name的值同字符串'Janis Joplin'进行比较,判断是否相等
unittest.main()
#不能用console窗口执行parse_args方法,一旦执行,就会导致console报错
================================ 
#如果测试通过,则会出现如下的类似结果。

-----------------------------------------------------------
Ran 1 tests in 0.000s
OK
Process finished with exit code 0
#运行测试用例时,每完成一个单元测试,Python都打印一个字符:
#测试通过时打印一个句点;测试引发错误时打印一个E;
#测试导致断言失败时打印一个F。

测试类

各种断言方法

unittest Module中的断言方法

方法 setUp()

import unittest
from survey import AnonymousSurvey
#相关代码及文件可在文末获取
class TestAnonymousSurvey(unittest.TestCase):
  """针对AnonymousSurvey类的测试"""
  def setUp(self): #Python会先运行setUp(),再运行各个以test_打头的方法
    """创建一个调查对象和一组答案,供使用的测试方法使用"""
    question = "What language did you first learn to speak?"
    self.my_survey = AnonymousSurvey(question)
    self.responses = ['English''Spanish''Mandarin']
#在setUp()方法中创建一系列实例并设置它们的属性,再在测试方法中直接使用这些实例
  def test_store_three_responses(self):
    """Test that three individual responses are stored properly."""
    for response in self.responses:
        self.my_survey.store_response(response)
    for response in self.responses:
        self.assertIn(response, self.my_survey.responses)
unittest.main()

Part3项目

Python的基础知识已经介绍完了,本书的第二部分是具体项实战,这一部分要求我们在个人实践中学习更多Python知识。大家的背景不同,所做的项目不同,接下来的部分,我也会主要写我感兴趣的部分。

我用的是windows 系统。

12项目1 外星人入侵

安装外部包

以conda为例,在PyCharm里有一种比较直观的方法,如图所示:

另一种方法是使用命令提示符(cmd)安装,也可以在PyCharm里的Terminal输入安装命令进行安装,我建议使用后者,前者可能会遇到路径相关的问题吧:

安装conda的时候,它还报错了,原因是未安装auxlib。

13项目2 数据可视化

最流行的工具之一是matplotlib,它是一个数学绘图库,一些基本的画图方法和代码可参考:

https://www.runoob.com/w3cnote/matplotlib-tutorial.html

https://matplotlib.org/stable/plot_types/index.html

14项目3 Web应用程序

建立虚拟环境

拟环境是系统的一个位置,你可以在其中安装包,并将其与其他Python包隔离。

Terminal #在终端输入下述代码
----------------------------
#(venv) 'C:\Users\ASUS\Desktop' 是当前路径,
#'>'之后才是输入的命令
(venv) C:\Users\ASUS\Desktop> pip install virtualenv #安装virtualenv
(venv) C:\Users\ASUS\Desktop> virtualenv ll_env #创建名为'll_env'的文件夹
(venv) C:\Users\ASUS\Desktop> ll_env\Scripts\activate #激活虚拟环境
(ll_env) C:\Users\ASUS\Desktop> deactivate #停止使用虚拟环境

Terminal 小技巧

  1. PyCharm里可以使用Ctrl+CCtrl+V的快捷键来完成复制粘贴操作。
  2. 即可查看上一条命令,按可查看下一条命令
  3. 在写命令的时候无论光标在哪,按backspace都会从最右边开始删除命令。按↓+backspace则可从光标所在位置向左开始删除命令。

正则表达式

正则表达式通常被称为regex,几乎每种编程语言都使用它。参考:

https://www.runoob.com/regexp/regexp-syntax.html

关于正则表达式还有相关的Python第三方包,如regex:

#先自己安装一下这个包,然后再运行如下代码查看帮助文档
import regex
help(regex.regex)
help(regex.Regex)

Part4写在文末

受文本限制,笔记里的代码写的紧凑了些。这本书挺适合Python初学者的,然后我在阅读的时候也发现了书上的一些小错误(可能是因为时间关系所产生的),不过大部分都能在网络上找到对应的解决方法。同时,我也重新整理了一下一些Python相关的电子书等资料,本文相关代码也顺便放里面了,后台回复20230115

顺便提前祝大家新春快乐,大家快领我制作的红包鸭:

红包封面审核被驳回了几次,现在还在审核中,过两天应该就可以发出来了。。。

还有一件事,点击左下角阅读原文应该会有小惊喜奥。

参考资料

  1. Python编程:从入门到实践线/(美)埃里克·马瑟斯(Eric Matthes)著;袁国忠译.--北京:人民邮电出版社,2016.7

声明:分享的部分资料来源于网络,仅用于学习交流,
如有侵权请联系删除。