Python入门-再读《Python编程:入门到实践》

《Python 编程:从入门到实践》

二、变量和简单数据类型

运行.py时发生的事情

Python解释器读取整个程序,确定其中每个单词的含义。看到单词print时,解释器就会将括号中的内容打印到屏幕,而不会管括号中的内容是什么。

变量

  • 变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头。
  • 变量名不能包含空格,但可使用下划线来分隔其中的单词。
  • 不要将Python关键字和函数名用作变量名。

当程序无法成功运行时,解释器会提供一个traceback。traceback是一条记录,指出了解释器尝试运行代码时,在什么地方陷入了困境。


字符串

Python中用引号括起的都是字符串,其中引号可以是单引号,也可以是双引号。

这种灵活性能够让我们在字符串中包含引号和撇号

"This is a string."
'This is also a string.'
'I told my friend, "Python is my favorite language!"'

一些函数

  • title() 让每个单词的第一个字母大写

  • upper() 让所有字符大写

  • lower() 让所有字符小写

  • 可以使用+进行字符串拼接

    • 在使用数字拼接时,要使用str()函数将其转换为字符再拼接
  • \t 制表 \n换行 \n\t换行并制表

  • strip()去除头尾空格,lstrip()去除头空格,rstrip()去除尾空格


单引号引起的语法错误

#true
message = "One of Python's strengths is its diverse community"
print(message)
#false
message = 'One of Python's strengths is its diverse community'
print(message)

数字

print(2 + 3)
print(2 * 3)
print(2 - 3)
print(2 / 3)
#整除
print(2 // 3)
#乘方
print(2 ** 3)

三、列表

列表由一系列按特定顺序排列的元素组成,可以将不同类型的数据放入列表。

创建列表

列表用方括号来表示,用逗号来分隔其中的元素。

list1 = ['111', 'aaa', 'bbb']
print(list1) // ['111', 'aaa', 'bbb']

操作列表元素

可以根据下表访问、修改列表元素。

python支持-1访问最后一个元素,-2指定倒数第二个元素,以此类推。

#列表末尾添加元素
list1.append('ccc')
#列表插入元素,右侧元素右移
list1.insert(index, 'ddd')
#删除元素
del list1[0]

#越界报错
pop = list1.pop()
pop1 = list1.pop(2)

#根据值删除,没有值会报错,只会删第一个值
list1.remove('aaa')

组织列表

#永久排序
list1 = ['aaa','111','bbb']
list1.sort() //默认升序排列
list1.sort(reverse=True)//降序排列
#如果列表中元素不可比较,会报错

#临时排序
list2 = sorted(list1)
list3 = sorted(list1, reverse=True)

#反转顺序,没有返回值,不能赋给另一个列表
list1.reverse()

#获取长度,如果列表为None,则报错
len(list1)

遍历列表

list1 = ['aaa','111','bbb']
for i in list1:
    print(i)

#由换行严格限制循环体范围
#for之后没有缩进,即没有循环体会报错
#不允许无效缩进,会报错
#冒号表示,下一行是循环的第一行,没冒号报错

range 创建数值列表

for value in range(1, 5):
    print(value)
#1 ~ 4 打印

#list()将range结果转化为列表
list2 = list(range(1,6))#1,2,3,4,5
list2 = list(range(1, 5, 2))#指定步长 1,3
list2 = list(range(7, 1, -2))#7, 5, 3

#简单聚合分析
a = min(list2)
b = max(list2)
c = sum(list2)

#列表解析
list3 = [value ** 2 for value in range(1,11)]

列表切片

list1 = ['aaa','111','bbb']
list2 = list1[0: 1] #aaa
list3 = list1[0: -1] #aaa, 111

#复制列表
list2 = list1 # 浅拷贝
list2 = list1[:] # 深拷贝

元组

不可变的列表 -> 元组

dims = (100, 20)
#修改元组元素会报错
for dim in dims:
    print(dim)

#元组不可修改,可以修改引用
dims = (200,30)

四、if

#检查是否相等
a = 1
if a == 1: print('equal')
if a != 2: print('not equal')

#多条件
and #与
or #或

#范围查找
list1 = ['aaa','111','bbb']
user = 'bbb'
if user in list1: print('in')
if user not in list1: print("not in")

if a == 1: print('aaa')
else: print('bbb')
    
    
if a == 1: print('aaa')
elif b == 1: print('bbb')
else: print('ccc')

列表是否为空

list1 = []
#if list1: #为false

list2 = None
#if list2: #为false

#但是list1仍是list,可以append,list2不支持append

五、字典

字典是一些列键值对

  • 键可以为None,值也可以为None
  • 键冲突时,输出后面的
  • 列表无法作为键,unhashable
  • 可以用dict['aaa']来访问、修改对应的值
  • 可以dict['bbb'] = 2来添加键值对
  • 使用del dict['aaa']来删除键值对
  • 最后一个元素可以多一个逗号

遍历

dict1 = {
    'username': 'aaa',
    'first': 'Alice',
    'last': 'Bob'
}

for key, value in dict1.items():
    print(key)
    print(value)
    
for key in dict1.keys():
    print(key)
    
for value in dict1.values():
    print(value)
    
    
#利用set方法去重
for value in set(dict1.values()):
    print(value)

嵌套

  • 允许嵌套,value可以为dict,可以为list,可以为dict

六、输入

input()

#input接受屏幕输入,可以传入提示信息
age_str = input("input your age\n")
age = int(age_str)
print(age >= 18)

#得到的是字符串,可以用int()将结果parse为Int,再进行比较

七、while

  • 通过条件控制
  • break
  • continue
cn = 0
while cn < 10:
    cn += 1
    #python不支持++
    
list1 = ['aaa','111','bbb']
list2 = []
while list1:
    list2.append(list1.pop())
    
list1 = ['aaa', '111', 'bbb', 'aaa']
while 'aaa' in list1:
    list1.remove('aaa')

八、函数

使用关键字def定义一个函数

def get_name():


参数

  • 位置实参,参数位置和形参位置相同

  • 关键词实参,通过指定关键字,来改变实参位置。

    • def describe_pet(animal_type, pet_name):
    • describe_pet(animal_type='hamster', pet_name='harry')
  • 默认值,形参可以指定默认值,传参时不传就使用默认值

    • def describe_pet(pet_name, animal_type='dog')
  • 传递任意数量的实参(可变形参)

    • def make_pizza(*toppings):
    • 可输入任意多个参数。
    • 形参名*toppings中的星号让Python创建一个空元组,并将收到的所有值都封装到这个元组中
  • 结合位置实参与任意数量实参

    • def make_pizza(size, *toppings):
    • 调用时按顺序调用即可。
  • 结合关键字实参与任意数量实参

    • 需要接受任意数量的实参,但预先不知道传递给函数的会是什么信息。可将函数编程写能够接受任意数量的键值对

    • def build_profile(first, last, **user_info):

    • build_profile('albert', 'einstein',location='priceton', field='physics')


传递参数

  • 基本类型:只传递副本,不更改原值
  • list、dict:传递引用,会更改原引用指向的对象。

导入模块

要让函数是可导入的,得先创建模块。

模块是扩展名为.py的文件


  • 导入整个模块
    • import pizza
    • 需要用pizza.make_pizza调用
  • 导入特定函数
    • from module_name import function_name
    • 直接调用
  • 导入多个函数
    • from module_name import function_a, function_b
    • 直接调用
  • 使用as给函数指定别名
    • from pizza import make_pizza as mp
  • 使用as给模块指定别名
    • import pizza as p
  • 导入模块中的所有函数
    • from pizza import *
    • 不推荐使用,每个函数都可以直接用函数名调用。容易混淆。如果模块中的函数名称有相同的,可能导致意想不到的结果。

函数编写建议

  • 函数指定描述性名称
  • 只使用小写字母和下划线。

九、类

class Dog():
    def __init__(selfm name, age):
        """初始化属性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!")

__init__(self, name, age)

构造方法,当创建Dog对象时自动调用。self相当于Java中的this指针。

在传参时不需要传入self,但是必须作为形参写入。

开头末尾的两个下划线是约定,避免Python默认方法与普通方法发生名称冲突。

以self为前缀的变量都可供类中的所有方法使用,可以通过类的任何实例来访问这些变量。


创建实例

my_dog = Dog('willie', 6)

大写的是类,小写的是实例


属性指定默认值

class Car():
    
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

修改属性值

  • 直接修改
  • 通过方法修改
    • def update_odometer(self, mileage):
    • self.odometer_reading = mileage

继承

一个类继承另一个类时,自动获得另一个类的所有属性和方法。

创建子类时,父类必须包含在当前文件夹,且位于子类前面。

__init__()

创建子类实例时,Python首先需要给父类的所有属性赋值。

class Car():
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
        
class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)

重写

重写的方法与父类方法同名


将实例作为属性

类似于Java的接口,又有点不像。

将类的一部分作为一个独立的类提取出来。将大类拆分成多个协同工作的小类。

class Car():
    --snip--
    
class Battery():
    def __init__(self, battery_size=70):
        selef.batttery_size = battery_size
        
    def describe_battery(self):
        print("This car has a " + str(self.battery_size) + "-kWh battery.")
        
class ElectricCar(Car):
    def __init__(self, make, model, year):
        super().__init__(make, model, year)
        self.battery = Battery()

导入类

同一个.py文件中如有多个同名类,后面的将覆盖前面的类

  • 导入单个类
    • from car import Car
    • 直接创建Car即可
  • 从一个模块中导入多个类
    • from car import Car, ElectircCar
  • 导入整个模块
    • import car
    • 通过模块名.类名的方式访问
  • 导入模块中的所有类
    • from module_name import *
    • 不推荐使用,这种方式不明确,还会导致名称困惑
  • 在一个模块中导入另一个模块
    • 一个模块需要其他模块

类编写建议

  • 类名采用驼峰命名法,每个单词首字母大写,不使用下划线
  • 实例名和模块名都小写,并在单词间加下划线。
  • 在类中用一个空行来分隔方法,在模块中用两个空行来分隔类。

十、文件

#读取整个文件
with open(filename, 'mode') as file_obj:
    contents = file_obj.read()
    
with open(filename, 'mode') as file_obj:
    contents = file_obj.readlines()
    
with open(filename, 'mode') as file_obj:
    contents = file_obj.readlines()
    
#with会自动在合适的时机关闭文件。
#可用open() close()替代,但时机需要额外的考虑
#读取文件前后可能有无用的换行符、空格,可用strip()等方法去除。
#mode 'w'只读, 'r' 只写, 'a' append追加写, 'r+' 读写模式
#写时没有某个文件会自动创建,w会覆盖,a会追加
#python只能写入字符串,数字要通过str()转换

JSON

使用json模块,可以操作json数据

import json

nums = [1,2,3,4,5]
filename = 'a.json'
with open(filename, 'w') as f_obj:
    json.dump(nums, f_obj)
    
with open(filename) as f_obj1:
    list1 = json.load(f_obj1)

十一、异常

#使用try-except-else来处理异常
try:
    print(5 / 0)
except ZeroDivisionError:
    print("You cannot divide by zero")
else:
    print("sth")
    
#try块成功运行时,会走else代码块
#FileNotFoundError
#split()方法会拆分文本,并返回一个列表
#这个split更高级,多个空格时会省略空字符串

#当发生错误时,什么事也不做,pass关键字
try:
    --snip--
except FileNotFoundError:
    pass
else:
    --snip

在重构代码时,尽量让函数有返回值,可以根据返回值来方便测试


十二、测试

Python标准库的模块unittest提供了代码测试工具。

  • 单元测试:用于核实函数的某个方面没有问题
  • 测试用例:一组单元测试
    • 良好的测试用例考虑了函数可能收到的各种输入
  • 全覆盖测试
    • 一整套单元测试,涵盖了各种可能的函数使用方式。
    • 对于大型项目,实现全覆盖很难

起手式

import unittest
from name_function import get_formatted_name

class NamesTestCase(unittest.TestCase):
    def test_first_last_name(self):
        formatted_name = get_formatted_name('janis', 'joplin')
        self.assertEqual(formatted_name, 'Janis Joplin')
        
unittest.main()
  • 继承unittest类
  • 测试方式test打头,这样才会在运行.py时自动运行
  • 使用断言assert判断是否符合预期

测试类

方法 用途
assertEqual(a, b) 核实 a == b
assertNotEqual(a, b) 核实 a != b
assertTrue(x) 核实 x为True
assertFalse(x) 核实 x为False
assertIn(item, list) 核实 item在list中
assertNotIn(item, list) 核实 item不在list中

setUp()方法

每个测试方法都创还能了一个对象实例。

unittest.TestCase类包含了setUp()方法,可以只创建一次对象,并在每个测试方法中使用。

import unittest
from survey import AnonyousSurvey

class TestAnonymousSurvey(unittest.TestCase):
    def setUp(self):
        """创建一个调查对象和一组答案,供使用的测试方法使用"""
        question = "What language did you first learn to speak?"
        self.my_survey = AnonymousSurver(question)
        self.responses = ['English', 'Spanish']

posted on 2022-10-04 17:25  茶倌  阅读(81)  评论(0)    收藏  举报