目录

======== 第四部分 Python进阶 ========

第一节 函数

4.1.1 函数定义及调用

4.1.2 函数的参数

4.1.3 函数的返回值

第二节 面向对象

4.2.1 面向对象基本概念

4.2.2 类和实例

4.2.3 对象的属性与方法

4.2.4 类属性与方法

4.2.5 一切皆对象

4.2.6 综合案例-电商购物车商品统计分析

4.2.7 自定义属性-property

第三节 模块和包管理

4.3.1 模块的导入

4.3.2 自定义模块

4.3.3 常用内置模块

datetime - 日期时间类型

time - 时间的访问和转换

random - 生成随机数

os - 操作系统接口

sys - 系统相关参数及函数


======== 第四部分 Python进阶 ========

第一节 函数                                                                       

在前面的学习过程中,我们已经接触了很多次函数,现在我们来好好的认识一下这个重要的小伙伴。函数就是一段可以重复调用的代码,在Python中函数是非常重要的概念,在编程中几乎无处不在。

4.1.1 函数定义及调用 

在Python在, 我们使用def关键字来定义函数

def hello(name):print("Hello", name)

上面的代码定义了一个 简单的函数,它的作用就是打印出"Hello"加一个名字。我们看看它的结构:

调用hello函数,将会打印“Hello, Python”

hello("Python")

在这个过程中发生什么什么事呢?这实际上是将name传递给hello函数,也就是将name的值设置为"Python",并执行函数体内的代码。

4.1.2 函数的参数                                                                                      

函数的参数可以有一个,也可以有多个,也可以没有参数。这取决于在定义函数的时候如何定义参数部分。刚才我们定义的函数只有一个参数,现在我们定义两个参数的函数。

def hello(name, sex):if sex == '男':print("Hello, Mr", name)elif sex == '女':print("Hello, Miss", name)

这个函数有两个参数,name和sex,分别表示用户的名字和性别,以便显示不同的尊称。我们在调用的时候,要注意参数的顺序,不能前后颠倒。调用函数:

hello("Zhang", "男")
hello("Wang", "女")

如果参数较多,记不清它们的顺序,可以写上参数名,这样就不用管顺序了。

hello(sex='男', name='Zhang')

如果说用户大多数是女的,只有少部分的男性,那这个函数还可以改造一下,我们让它的sex参数默认就是“女”:

def hello(name, sex='女'):if sex == '男':print("Hello, Mr", name)elif sex == '女':print("Hello, Miss", name)

和上面的函数相比,只是在sex参数后面加上一个默认值,这样,后面用户没有填性别信息的时候,就会默认为女性。

hello("Wang")

如果每一个参数都有默认值,在调用的时候甚至可以不传参数。

def hello(name='Anonym', sex='女'):if sex == '男':print("Hello, Mr", name)elif sex == '女':print("Hello, Miss", name)hello() # Hello, Miss Anonym

现在这个函数对于信息不完整的数据也有处理能力了。

4.1.3 函数的返回值                                                                                   

如果将函数比做一名员工,调用函数的我们就是老板,老板给员工一些具体的指示,员工则按规定好的流程去做事。有一些事情,比如老板说去打扫一下厕所,员工就默默地去干活了,干完了就完事了。如果是一些需要回复的事情,比如老板让员工去算一下去年公司的收入,那老板的意思肯定是要知道 后算出来的那个数字。对于函数也是一样,有一些函数我们是需要知道执行的结果。

def multiply(num1, num2):return num1 * num2
n = multiply(2, 4)
print(n) # 8

multiply函数的功能是计算两个数相乘,我们传入两数字作为参数,希望能得到一个这两个数相乘的结果。

multiply的最后一行使用return 关键字将结果返回。通常在函数的最后一行返回结果,但有时候也有多种可能。

def permit(age):if age >= 18:print("准许进入")return Trueelse:print("禁止进入")return Falseprint("end")

multiply的 后一行使用return关键字将结果返回。通常在函数的 后一行返回结果,但有时候

上面我们定义了一个只允许成年人进入的函数,如果年龄大于等于18岁,返回True,表示允许通过;如果小于18岁则不允许。虽然有两个return语句,但只返回一个结果,要么返回True要么返回False。注意在return语句执行完后,函数就会结束执行,在它之后的任何语句都不会再执行,所以上例中的“end”无论怎么样都不会被打印。

如果一个函数内没有任何return语句,那它的返回值就是None。

def do_nothing():pass
print(do_nothing()) # None

4.1.4 匿名函数

有时候我们临时需要一个函数,且它的逻辑比较简单,这时候就可以定义匿名函数。

lambda n: n * n

这就定义了一个匿名函数,这个匿名函数接收一个数值参数,计算出这个数的平方值并返回,就相当于下面的函数

def square(n):return n * n    

lambda是Python中的关键字,它的作用就是用来定义匿名函数,匿名函数的函数体一般只有一行代码,省略了函数名和返回值语句。

这样的函数它的作用是什么呢?什么时候需要使用匿名函数而不是函数呢?回忆一下,我们在学习列表排序的时候用过一个匿名函数,现在是时候重温一下了。

revenue = [('1月', 5610000), ('2月', 4850000), ('3月', 6220000)]
revenue.sort(reverse=True, key=lambda x:x[1])

列表的sort函数key参数,它只能接收一个函数类型的值。单独看一下这段匿名函数:

key = lambda x: x[1]

现在key就是一个函数了,我们来调用一下它,x[1]这种索引操作说明x肯定是个序列,且长度至少为2。

key([1, 2]) # 2
key("abcd") # 'b'

key函数的作用就是返回序列中的第二个元素,在sort排序的时候就会以每个元素的第二个元素作为比对的依据。在这个例子中,第二个元素就是月收入,所以是不是达到了以月收入排序的目的了?

这样的一个简单的功能,我们用不着单独定义一个函数,即用即抛,就像一次性手套一样,这正是匿名函数的使用场景。

值和引用*  

作用域/global*   

yield表达式*

可变参数*

装饰器*   

第二节 面向对象  

4.2.1 面向对象基本概念 

面向过程:根据业务逻辑从上到下写代码。

面向对象:将变量与函数、属性绑定到一起,分类进行封装,每个程序只要负责分配给自己的功能,这样能够更快速的开发程序,减少了重复代码。

我们在前面写的代码都是面向过程的,这对初学者比较容易接受,而且,对于比较简单的需求,用面向过程实现起来确实更简单。

那什么是对象呢 ?我们可以理解为实际存在的实物,比如一个用户、一台ATM机、一幢建筑,亦或者是软件业务流程中产生的虚拟概念,比如订单、购物车、用户账户。我们发现,不管是实体还是虚拟产物,它们都是有一些共同点,都是名词,有自己的行为,有自己的属性。比如说用户对象,用户都有相同的几个属性,名字、年龄、性别、注册时间、上一次登录的时间等等。但不同用户这个几属性的值却都不一样。下面我们来看几个例子。如果你想向另一个人描述一只狗,那你会说出这只狗的哪几个特点?品种颜色

体型大小

狗会有哪些行为呢?

吃东西奔跑吠叫

这些都是我们基于常识总结出来的狗的特点和行为,对象的属性就是可以精确描述事物的特点,对象的函数就是事物的行为。

4.2.2 类和实例

现在我们用代码来实现一下“狗”对象,先介绍Python里的一个重要概念:类,它也是面试对象编程的基础。

class Dog:pass

这样我们就定义了一个类,使用class关键字,加上一个类名,这样我们就定义了一个空的类。

类名一般使用名词,且使用驼峰式命名法。

类是创建对象的模板,对象是类的实例。类就像生产线,有了类,就可以生产出许许多多的相同对象。

使用上面的Dog类来创建一个Dog对象:

dog = Dog()
type(dog)

这里dog就是Dog的实例,通过内置的type函数,可以查看任何对象的类。

type(1)
type('abc')
type([])

这些都是我们学习过的数据类型,我们看到它们分别是整数、字符串和列表。那dog的类型就是Dog。

如果我们不知道一个对象是不是某种类型,就可以用type判断。

type('abc') == str # True
type(dog) == Dog # True
type(1) == int # True

也可以使用内置函数isinstance来判断对象与类的关系

isinstance('abd', str) # True
isinstance(1, int) # True
isinstance(dog, Dog) # True

4.2.3 对象的属性与方法                                                                             

现在我们来完整的实现一下Dog 类

class Dog:def __init__(self):self.breed = Noneself.color = Noneself.size = Nonedef eat(self):print("I like bones")def run(self):print("I'll catch you.")def bark(self):print('Wang! Wang!')

大家应该注意到,类的每一个方法的第一个参数是self ,但在调用的时候却不需要传参数给它。它是类方法和普通函数的区别,这个self代表的是实例自身,意思是“我的”,现在我们来创建Dog的实例

dog = Dog()
dog.eat()
dog.run()
dog.bark()
print('一只%s型%s色的%s' % (dog.size, dog.color, dog.breed))

调用不同的方法能打印出不同的内容,体现了不同的行为。但是最后一句话打印出来的内容却是None,因为我们还没有设置相应的属性。

dog.breed = '哈士奇'
dog.color = '黑白'
dog.size = '大'
print('一只%s型%s色的%s' % (dog.size, dog.color, dog.breed))
# 一只大型黑白色的哈士奇

如果每个创建完每个对象之后还要一个个的设置属性,会很麻烦。我们可以使用__init__ 函数来接收初始化参数,这样就可以把属性的值作为参数在初始化对象的时候就传给它。大家应该也注意到了,__init__ 函数看起来与众不同的样子,它是Python的类用来初始化对象的构造函数,它的名字是固定的,必须这样写,创建对象时会首先调用它。改完后构造函数后代码如下:

class Dog:def __init__(self, size, color, breed='土狗'):self.breed = breedself.color = colorself.size = sizedef eat(self):print("I like bones")def run(self):print("I'll catch you.")def bark(self):print('Wang! Wang!')

现在再来创建对象:

dog = Dog('中', '黄')
print('一只%s型%s色的%s' % (dog.size, dog.color, dog.breed))

第三个参数breed因为给了它默认值,所以可以不用传。

我们在之前学习的字符串、列表的所有函数,实际是调用字符串对象、列表对象的方法。

对象自身的属性是直接可以方法里使用的,比如我们改造一下bark方法,让狗可以开口自我介绍

class Dog:def __init__(self, size, color, breed='土狗'):self.breed = breedself.color = colorself.size = sizedef eat(self):print("I like bones")def run(self):print("I'll catch you.")def bark(self):print('我是一只%s型%s色的%s' % (self.size, self.color, self.breed))

这里在bark方法里使用的self和构造函数里的self一样,都是指向对象自身。

dog = Dog("小", "棕", "泰迪犬")
dog.bark()

4.2.4 类属性与方法                                                                                   

对象是从类创造的,对象的属性和方法虽然是在类中定义的,但它们的值是各个对象独有的,互相不能共享。而类也有属性和方法,且它们可以和类创建的所有对象共享。我们先来定义一个类

class Goods:def __init__(self):self.name = ''self.price = 0self.discount = 1

Goods类有三个对象属性,每个商品有自己的名称、价格、折扣。我可以随意的创建商品

g1 = Goods()
g2 = Goods()

但如何知道一共创建了多少个商品呢?我们可以给Goods类加一个计数器。

class Goods:count = 0def __init__(self):Goods.count += 1self.name = ''self.price = 0self.discount = 1        

我们给Goods类加了一个属性count,每当调用__init__ 函数时将它加1,这样我们就可以知道一共创建了多少商品对象了。这个count就是类属性,它可以通过对象访问,也可以通过类访问。

g1 = Goods()
g1.count # 1
g2 = Goods()
Goods.count # 2

即使没有定义对象,也可以直接访问count属性,这就是类属性,同样,类方法也不需要创建对象,通过类名就可以访问。我们改造一下Goods类,给它增加一个属性id,表示商品唯一的序列号,为了保证 id不重复,我们使用计数器,每创建一个商品给它加1。

class Goods:id_count = 0@classmethoddef generate_id(cls):cls.id_count += 1return cls.id_countdef __init__(self):# zfill函数表示用“0”将数字补足5位self.id = str(self.generate_id()).zfill(5)self.name = ''self.price = 0self.discount = 1

这里的generate_id 方法就是一个类方法,它的上面一行有一个@classmethod ,声明了它是类方法,它的参数不再是self,而是cls,指向类本身,用来在类方法内部访问类成员属性和方法。这个方法每次将id_count属性加1,并返回。

这种@ 符号的写法叫做装饰器,装饰器是用来装饰函数的,不同的装饰器赋予函数不同的特殊功能。对于classmethod装饰器,大家只要知道它是用来定义类方法的就行了。

现在我们再来试试:

g1 = Goods()
g2 = Goods()
g1.id # 00001
g2.id # 00002
Goods.id_count # 2

4.2.5 一切皆对象                                                                                      

在Python中一切都是对象,我们使用的数字、字符串、函数甚至类本身,都是对象。所有的对象都可以用type函数来判断它的类型,同时可以用dir函数来查看它的属性和方法。

dir(dog)

会显示出dog对象的所有属性和方法,包括刚刚定义的那几个方法和属性。对于对象,也可以使用help 函数查看它的帮助文档。

help(sum)
help(print)

这些帮助信息可以在定义的时候写入到代码里:

def bark(self):"""一只狗的自我介绍"""print('我是一只%s型%s色的%s' % (self.size, self.color, self.breed))    

加上这句文档后,我们就可以使用help函数查看bark方法的帮助信息了,这有助于其他人使用我们的方法。

help(dog.bark)
help(Dog.bark)

一切皆对象是一句简单的话,但它的精神却很深邃,试试下面的代码,你还能看得懂吗?

lst = []
lst.append(Dog)
dog = lst[0]('中', '黄')
lst.append(dog)
lst[1].bark()
lst[1].sleep = lambda: print('Good night.')
lst.pop().sleep()

有时候两个对象的值完全相同,我们可以说这两个对象是相等的,但不能说它们是同一个对象。

l1 = [1, 2, 3]
l2 = [1, 2,]l1 == l2 # False
l2.append(3)
l1 == l2 # True
l1 is l2 # False

最后一行操作,使用is 关键字来判断这两个对象是否是同一个对象,结果是False。它表明l1和l2是不同的对象,这一点可以使用id函数看出来:

id(l1)
id(l2)

分别返回两串不同的数字,这个一长串的数字代表了对象所指向的内存空间地址。

4.2.6 综合案例-电商购物车商品统计分析                                                       

项目需求:可以设置每个商品的名称、价格、折扣率,用户将商品加入到购物车以后,能够立即显示所有商品、总价、折扣情况和实际需要支付的金额,也就是折扣后的金额。商品的名称、价格、折扣率都可以随意修改,且修改完成后,购物车中的相关信息和金额也会发生改变。

需求分析:在这个需求里面,提到了两个虚拟产物,商品与购物车,也就是说需要定义两个类。

class Goods:"""商品类"""id_count = 0@classmethoddef generate_id(cls):cls.id_count += 1return cls.id_countdef __init__(self, name, price, discount=1):self.id = str(self.generate_id()).zfill(5)self.name = nameself.price = priceself.discount = discountdef calc_price(self):"""计算商品打折后的实际价格"""return self.price * self.discount

这是商品类,它有四个属性:ID、商品名称、价格、折扣,另外它还有一个函数,计算出商品打完折后的价格。接下来我们来创建几个商品对象:

g1 = Goods('iPhone 11', 6000, 0.9)
g2 = Goods('U盘32G', 100, 0.8)
g3 = Goods('华为P40', 5000)

这样我们就创建了三个商品对象,并设置好了它们的名称、价格、折扣。接下来我们来编写购物车类:

class Cart:"""购物车"""def __init__(self):self.cart = {}self.goods_list = []def add(self, goods, num=1):"""向购物车中添加商品"""if goods in self.goods_list:self.cart[goods.id] = self.cart[goods.id] + numelse:self.goods_list.append(goods)self.cart[goods.id] = numdef remove(self, goods, num):"""从购物车减少或删除商品"""if goods not in self.goods_list:returnself.cart[goods.id] -= numif self.cart[goods.id] <= 0:del self.cart[goods.id]self.goods_list.remove(goods)def get_goods_by_id(self, id):"""根据商品名称查找商品"""for g in self.goods_list:if g.id == id:return gdef get_total_amount(self):"""获取当前购物车中的总价"""amount = 0for name, num in self.cart.items():goods = self.get_goods_by_id(name)amount += goods.price * numreturn amountdef get_pay_amount(self):"""获取实际需要支付的总价"""amount = 0for name, num in self.cart.items():goods = self.get_goods_by_id(name)amount += goods.calc_price() * numreturn amountdef show(self):"""显示当前购物车中所有商品的数量、价格,以及总价"""title = ('商品', '单价', '数量', '价格(元)')def show_row(row):"""内部函数,显示购物车中的一行"""for col in row:print(str(col).ljust(12), end='\t')print()print("-" * 70)show_row(title)for id, num in self.cart.items():goods = self.get_goods_by_id(id)price = '%.2f' % goods.priceif goods.discount < 1:price = '%.2f (%d折)' % (goods.price, goods.discount * 10)show_row((goods.name, price, num, '%.2f' % (goods.calc_price() * num)))total_amount = self.get_total_amount()pay_amount = self.get_pay_amount()discount_amount = total_amount - pay_amountshow_row(('', '', '', '总金额: %.2f' % total_amount))if discount_amount > 0:show_row(('', '', '', '优惠: %.2f' % discount_amount))show_row(('', '', '', '实付金额: %.2f' % pay_amount))    

这是购物车类,看起来它的代码很长。共有两个属性,6个方法。其实这个类主要就是提供了三个功能:

增加商品  add

减少商品  remove

显示商品  show

其他的函数都是辅助实现这三个主要功能。cart是一个字典,用来保存商品和数量的对应关系,它的键名是商品ID(字符串);goods_list是一个列表,保存了购物车所有商品的详细信息(商品类实例),注意它们的数据结构。有了Goods和Cart,我们就可以随意的增加删除商品,并可以随时查看购物车里的情况。

cart = Cart()
cart.add(g1)
cart.add(g2, 3)
cart.show()

显示如下:

商品                     单价           数量           价格(元)

iPhone 11    6000.00 (9折)       1            5400.00

U盘32G        100.00 (8折)        3            240.00

总金额: 6300.00

优惠: 660.00

实付金额: 5640.00

我们可以继续增加或者删除,并随时可以查看购物车的商品、计算总金额。如果商品的数量为零,则会从购物车中被删除

cart.remove(g2, 2)
cart.show()cart.remove(g2, 1)
cart.show()

如果商品的名称、价格或者折扣发生了变化,我们只需要修改商品对象就可以了,其他的代码都不用修改,购物车中的信息会实时的跟随调整。

cart.add(g3)
cart.show()
g3.name = '华为P40 pro'
cart.show()

可以看到,在修改了g3对象的商品名称之后,再次显示购物车时发生了变化 ,而我们的Cart类不用修改任何代码,这样做到了不同实体之间的操作隔离,是不是有点感受到面向面向对象的便捷了呢?

4.2.7 自定义属性-property

Cart类中的这两个函数get_total_amount 和get_pay_amount ,每次调用它们的时候都是直接调用,没有传递任何参数,最后返回一个值。对于这种方法,其实可以把它们变成property(属性):

@property
def total_amount(self):"""获取当前购物车中的总价"""amount = 0for name, num in self.cart.items():goods = self.get_goods_by_id(name)amount += goods.price * numreturn amount@property
def pay_amount(self):"""获取实际需要支付的总价"""amount = 0for name, num in self.cart.items():goods = self.get_goods_by_id(name)amount += goods.calc_price() * numreturn amount

我们在函数名前面加了一个property装饰器,修改方法名,去掉了get_ ,其实方法名也可以不改,在这里修改是为了代码的可读性更通顺。改造后,使用这两个方法时,就可以像使用普通属性一样:

cart.total_amount
cart.pay_amount

这样使用起来是不是更简洁优雅了呢?

继承*   

魔术方法*

第三节 模块和包管理   

Python中具有丰富的标准库和第三方库,学习并掌握模块、包的概念尤为重要,决定了我们是否能够利用这些丰富的资源,以及如何妥善组织好我们自己的代码。

4.3.1 模块的导入                                                                                      

首先,我们来导入一个内置模块

import math

math是Python标准库中的一个模块,用来进行数学运算,我们在上面使用import 关键字将它导入了,现在我们就可以使用它的功能啦。

# 求一个数的平方根
math.sqrt(4)

现在我们可以使用math模块里的所有函数了,可以使用dir来看一下都有哪些函数

dir(math)

我们也可以使用from ... import ... 这种语句来具体导入某一个子模块或函数

from math import sqrt
sqrt(4)

这种方式更精确的导入某个函数,使用起来更方便, 但要注意重名的问题。如果说我们的代码本来就有一个叫sqrt的函数,那我们可以使用as 关键字来给模块起一个别名

from math import sqrt as squarte
def sqrt(num):pass
squarte(4) # 2

或者是这样:

import math as math2
math = 0
math2.sqrt(4) # 2

有时候需要一次性导入多个模块,可以这样写

import sys, os
from math import sqrt, pow

注意,在实际调用模块之前,必须先导入,否则将会产生报错。

# 将会产生NameError
math.sqrt(4)
import math

如果导入一个不存在的模块,也会产生报错

# 将会产生ModuleNotFoundError: No module named 'maht'
import maht

4.3.2 自定义模块                                                                                      

除了使用标准库的模块,我们也可以自己定义模块,实际上,这也是我们在项目中组织代码的基本方式。以上一个综合案例“电商购物车”为例,实际的文件结构应该是这样的:

└── project├── cart.py # Cart类├── goods.py # Goods类└── main.py # 入口文件

shopcart目录里面,有三个文件,不同的类写在不同的文件内,cart.py和goods.py文件和原来保持一致即可。我们来看看main.py

from cart import Cart
from goods import Goodsg1 = Goods('iPhone 11', 6000, 0.9)
g2 = Goods('U盘32G', 100, 0.8)
g3 = Goods('华为P40', 5000)cart = Cart()
cart.add(g1)
cart.add(g2, 3)
cart.show()

main.py作为项目的入口文件,我们实际运行的时候就是从它启动

python main.py

那Python解释器是怎么找到cart和goods模块的呢?因为它们和main.py在同一个目录下,所以可以自动的发现它们。那如果有很多这样的模块,我们想把它们放到同一个目录下,以便统一管理,该怎么做呢? 比如,需要将cart.py 和 goods.py放到shopcart包内,调整目录结构如下:

├── project
│     ├── main.py
│     └── shopcart
│         ├── __init__.py
│         ├── cart.py
│         └── goods.py

如果发现目录内有名为__pycache__ 的文件夹,那是Python在导入时自动生成的缓存文件,可以忽略。

from shopcart.cart import Cart
from shopcart.goods import Goods

在mian.py同级目录下,多了一个shopcart目录,注意,shopcart目录里除了cart.py和goods.py目录,还多了一个__init__.py ,这是一个空文件,它的文件名看起来很奇怪,这是Python规定的命名规范,只要目录有一个名为__init__.ppy 的文件,则将这个目录视为包(package),现在修改main.py,作一下调整:

if __name__ == '__main__':g1 = Goods('iPhone 11', 6000, 0.9)g2 = Goods('U盘32G', 100, 0.8)g3 = Goods('华为P40', 5000)cart = Cart()cart.add(g1)cart.add(g2, 3)cart.show()

__name__ 表示当前文件所在模块的名称,模块可以通过检查自己的 __name__ 来得知是否运行在main 作用域中,这使得模块可以在作为脚本运行时条件性地执行一些代码,而在被 import 时不会执行。

4.3.3 常用内置模块                                                                                   

除了上面使用过的math模块以外,Python还有大概100多个内置模块,下面我们来介绍一下常用的几个模块。

datetime - 日期时间类型     

datetime模块中包含了几个常用的日期时间类,其中 常用的是datetime和timedelta。

注意,我们在下面使用的datetime是指datetime类而不是datetime模块。

from datetime import datetime, timedelta
# 返回当前时间的datetime对象
now = datetime.now()
type(now)
# 查看当前时间的年、月、日
print(now.year, now.month, now.day)
# 查看当前时间的时间戳,精确到微秒
now.timestamp()

计算机中时间的起始点都是1970年1月1日00:00:00,时间戳就是从1970年1月1日00:00:00到现在总秒数。所以如果时间戳A比时间戳B的值小,说明A在B之前。

datetime也提供将日期时间对象和字符串相互转换的操作,这在处理数据时会经常使用。

# 返回指定格式的日期字符串, 下面的返回 "2020-08-10 20:29:41"
datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# 将指定格式的字符串转换为日期时间对象
datetime.strptime('2020-01-01 00:00:00', '%Y-%m-%d %H:%M:%S')

%Y这种形式是日期时间的格式代码,下面是一些常用的代码含义:

代码

含义

示例

%Y

十进制数表示的带世纪的年份。

2019,2020

%m

补零后,以十进制数显示的月份。

01, 02, ..., 12

%d

补零后,以十进制数显示的月份中的一天。

01, 02, ..., 31

%H

以补零后的十进制数表示的小时(24 小时制)。

00, 01, ..., 23

%M

补零后,以十进制数显示的分钟。

00, 01, ..., 59

%S

补零后,以十进制数显示的秒。

00, 01, ..., 59

还有很多格式,可以查看Python官方文档:

https://docs.python.org/zh-cn/3/library/datetime.html#strftime-strptime-behavior

只要得到了datetime对象,我们就可以把它转换成各种格式。同样,只要有一个相对标准化的格式,我们就可以将它转换为datetime对象。

得到datetime对象后,可以对它进行修改,显示去年的今天现在这个时候的时间:

now = datetime.now()
last_year = now.replace(year=2019)
print(last_year.strftime('%Y-%m-%d %H:%M:%S'))

如果我们想知道两个datetime对象之间相差多长时间,可以将这两个对象相减

delta = now - last_year
type(delta)

得到的对象就是一个timedelta对象,我们可以根据timedelta对象知道这两个时间相差多少天多少分多少秒。

delta.days
delta.seconds

现在得到delta就是一个timedelta对象, 它表示366天整的时间,我们也可以将一个datetime对象和一个timedelta对象相加,将会得到一个新的datetime对象:

now + delta

将当前时间加上366天,就是明年的明天。timedelta类提供了非常便捷的方式帮我们处理日期时间,比如我们想要构造:

# 从当前开始20天后的时间
datetime.now() + timedelta(days=20)
# 两个半小时之前的时间
datetime.now() - timedelta(hours=2, minutes=30

time - 时间的访问和转换   

还有一个经常使用的时间模块time

import time
# 返回当前时间戳
time.time()
# 返回当前时间的格式化字符串
time.strftime('%Y-%m-%d %H:%M:%S')

其实time模块的另一个函数我们也经常使用,它可以使我们的程序暂时睡一会儿

print("好累呀,我要小睡3秒钟")
time.sleep(3)
print("好啦,我又元气满满!")

sleep函数会将当前的程序暂停若干秒数。

random - 生成随机数

准确的说是生成伪随机数,这是一个数学问题。默认random模块会根据当前的系统时间作为随机数种子,所以可以保证生成的随机数不会重复。

# 生成一个随机浮点数,范围[0.0, 1.0)
random.random()
# 生成1到100之间的随机整数,包括1和100
random.randint(1, 100)
# 从序列中随机抽出一个元素
random.choice(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
# 从序列中随机抽出k个元素,注意抽出来的元素可能会重复
random.choices(['a', 'b', 'c', 'd', 'e', 'f', 'g'], k=2)
# 跟choices函数类似,但它是不重复的随机抽样
random.sample(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
# 将一个序列随机打乱,注意这个序列不能是只读的
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
random.shuffle(lst)

os - 操作系统接口

os模块提供了一种使用与操作系统相关的功能的便捷式途径。需要大家了解一些操作系统的知识。

# 获取当前目录的路径
os.getcwd()
# 创建指定目录
os.mkdir(path)
# 与 mkdir() 类似,但会自动创建到达最后一级目录所需要的中间目录。
os.makedirs(path)
# 返回一个列表,该列表包含了 path 中所有文件与目录的名称。
os.listdir()

另一个很常用的子模块就是os.path,它提供了常用的路径操作。

# 显示当前目录的绝对路径
os.path.abspath('./')
os.path.abspath("__file__")

在大部分操作系统中,一般用. 表示当前目录,用.. 表示父级目录

相对路径:相对于当前目录的路径

绝对路径:以根目录为开始的路径(windows和Mac、Linux的根目录不同)

目录分隔符:windows 是 \ , Mac 和 Linux中是 /

# 如果 path 是 现有的 目录,则返回 True。
os.path.isdir(path)
# 如果 path 是 现有的 常规文件,则返回 True。
os.path.isfile()
# 目录分隔符
os.sep
# 合理地拼接一个或多个路径部分。
os.path.join(path, *paths)
# 返回路径 path 的目录名称
os.path.dirname("/tmp/test.txt") # '/tmp'
# 返回路径 path 的基本名称,文件名或是最后一级的目录名
os.path.basename("/tmp/test.txt") # 'test.txt'
os.path.basename("/tmp/test") # 'test'

sys - 系统相关参数及函数  

首先看的是sys.path,它返回的是一个列表,包含了若干个路径,它表示的是Python查找包的路径顺序,第一个是一个空字符串,它表示当前目录。之所以我们使用import 语句可以导入模块,靠的就是它。

sys.path
['','/Users/envs/py3/bin','/Users/envs/py3/lib/python36.zip','/Users/envs/py3/lib/python3.6','/Users/envs/py3/lib/python3.6/lib-dynload','/Users/envs/py3/lib/python3.6/site-packages','/Users/envs/py3/lib/python3.6/site-packages/pyspider-0.3.10-py3.6.egg','/Users/envs/py3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg','/Users/envs/py3/lib/python3.6/site-packages/IPython/extensions','/Users/.ipython']

sys.argv 表示启动的时候传递给Python脚本的命令行参数。

import sys
if __name__ == '__main__':print("Hello", end=' ')if len(sys.argv) > 1:print(' '.join(sys.argv[1:]))

上述是一个Python脚本hello.py 的代码,现在我们试着用不同的方式启动它

python hello.py
python hello.py Bill
python hello.py Mr Gates

我们会看到每次的输出不一样,再加两行代码,看一看sys.argv是什么?

# sys.argv是个列表
type(sys.argv)
print(sys.argv)

可以看到sys.argv是一个列表,它的第一个元素就是脚本的文件名。所以传递它的启动参数,都会放在列表的后面。我们可以使用这种方式接收用户传递的参数。

7.1.3 Python进阶 《函数》定义、调用,参数,返回值《面向对象》概念,类,实例,对象,属性,方法《模块、包》导入,自定义,常用内置:datatime,time,random,os,sys相关推荐

  1. python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce、map、filter)

    python函数+定义+调用+多返回值+匿名函数+lambda+高级函数(reduce.map.filter) Python 中函数的应用非常广泛,比如 input() .print().range( ...

  2. python怎么调用函数的返回值类型,10、Python基础之函数的调用与返回值

    一.函数参数 1.1 不定长参数 当我们定义函数时,可能需要定义一个函数能处理比当初声明时更多的参数,这些参数叫做不定长参数. 我们可以在形参前面加上一个 * ,这样这个形参就可以获取所有的实参,它将 ...

  3. python内置方法怎么使用_python的常用内置方法

    __author__ = 'coco' ''' python内置函数 ''' # all() 全为真,才为真 print(all([0,-2,3])) # False print(all([1,-2, ...

  4. python组合和继承的区别_Python开发之面向对象、类和对象、组合与继承的实例讲解...

    一.面向对象 如何创建一个类 class Xxxx: dic={xxx:xxx,xx:xx,x:x} #属性 def __init__(self,xxx,xxx,xxx): # 定义属性 def ac ...

  5. API数据调用参数返回值说明

    item_search-按关键字搜索 1.公共参数 请求地址:https://console.open.onebound.cn/console/index.php?i=hardy 名称 类型 必须 描 ...

  6. python update函数会调用哪些内置函数_Python函数之内置函数

    截止导Python 3.6 目前内置函数有68个 以下是对这些内置函数的分类 一:作用域相关 以字典的形式返回作用域中的名字 locals # 返回本地作用域的所有名字 globals # 返回全局作 ...

  7. java beetl 视频_04.Beetl常用内置函数以及安全输出---《Beetl视频课程》

    本期视频实现了三个功能,模糊搜索.标签分类.登录/注销功能: 内容简介:使用了常用内置函数,以及安全输出,实现了上面提到的三个业务 作者:GK 常用内置方法 date 返回一个java.util.Da ...

  8. python学习之路---函数:定义def、调用、返回值return、参数说明、参数陷阱

    #函数 #可读性强,复用性强 #函数定义:定义了之后,可以在任何需要的地方调用 #格式: def 函数名(): 例子:def mylen(): # 没有返回长度,只能单纯的打印 # return 返回 ...

  9. python中函数的调用_慢步python,编程中函数的概念,python中函数的声明和调用

    函数,曾经是一个很高大尚的概念.笔者是在高中数学里认识的函数,先是从y=2x+3 这条代数式开始的.y是因变量,x是自变量,y因为x取值的变化而变化. 再后来式子变成这样:f(x)=2x+3,f(x) ...

  10. python函数参数定义顺序_18 Python - 函数定义与参数

    12 函数定义与参数 01函数 (1)定义: def 函数名(参数1,参数2--): 函数体 return 结果 (2)调用: 函数名(实际参数) (3)函数作用: 最大化代码重用, 最小化代码冗余, ...

最新文章

  1. 团体程序设计天梯赛-练习集L1-013. 计算阶乘和
  2. oracle如何复制dept,[oracle]表复制的sql语句
  3. c语言实现辗除法,辗除法什么东西哦?
  4. python在线翻译脚本_用python实现百度翻译的示例代码
  5. 未定义标识符 stringc/c++(20)_Python 标识符命名规则
  6. Service order description modify and save
  7. python导包路径问题_python的导包问题
  8. Keepalived实战(3)
  9. qt高级编程附源码_c++ gui qt4编程附源码
  10. 步进电机、伺服电机、舵机、无刷电机、有刷电机区别
  11. Android屏幕共享与直播-red5流媒体服务器搭建
  12. cefsharp 添加html,winform+cefSharp实现窗体加载浏览器
  13. 第一次发博客,随便说说
  14. 爬豆瓣电影top名单
  15. 研究生的压力应对与心理健康 测试题答案
  16. Android小钢琴
  17. 批量删除html网页,ie浏览器收藏夹网页批量删除方法
  18. edgexfoundry docker 容器化部署 ubuntu16.4 跑起来 go0.6.0 版
  19. 那些年让人迷惑的同步、异步、阻塞、非阻塞
  20. SAP vf11发票冲销

热门文章

  1. 安装群晖系统入门图文教程
  2. linux的系统文件位置,剖析Linux系统中的文件系统路径
  3. 个人财务流水账系统c语言,微易个人财务收支管理系统的教程
  4. CISP-PTE证书含金量大吗?一文看懂CISP-PTE值不值得考
  5. 根据印刷行业的特点,整理出MES管理系统解决方案
  6. 不藏了,我的一千行 MySQL 学习笔记(2万字长文)
  7. xz2显示无法连接服务器,微端网页版无法登入问题解决方法
  8. 手机上怎么将图片转换成PDF
  9. importOrder
  10. CloudFlare的Worker免费部署服务