Python基础,主讲:汤小洋
一、Python简介
1. Python是什么?
Python是一种面向对象的解释型计算机程序设计语言,由荷兰人Guido van Rossum(龟叔)于1989年发明,第一个公开发行版发行于1991年。
诞生:1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,即Python(TIOBE编程语言排行榜)
作用:开发网站、后台服务、工具脚本、爬虫、数据分析、人工智能等
特点:
优点:简单(定位:简单、优雅、明确)、代码量少(人生苦短 我用python)、功能强大(大量的第三方库)
缺点:运行速度慢、代码不能加密
补充:Python是一门解释型语言,不需要编译,类似于PHP,不同于Java、C#等编译型语言
2. 安装Python
Python是跨平台的,执行Python代码需要解释器
版本:2.x、 3.x
安装步骤:
Windows
Linux
mkdir python # 创建Python的安装目录
tar zxf Python-3.6.5.tgz # 解压缩
cd Pyton-3.6.5
./configure --prefix=/home/soft01/python # 配置,指定安装位置
make # 编译
make install # 安装
cd /home/soft01/python/bin
./python3
# 将python路径添加到PATH变量中
vi ~/.bashrc
export PATH=/home/soft01/python/bin:$PATH
source ~/.bashrc
二、第一个Python程序
1. 使用Python交互模式
执行python命令,就进入Python交互模式,提示符>>>,输入exit()退出交互模式
>>> 3+8
11
>>> print("Hello World")
Hello World
>>> name="tom"
>>> print(name)
tom
>>>exit()
2. 使用文本编辑器
建议使用sublime或notepad++等,不要使用windows自带的记事本(会自动在文件的开头添加特殊字符)
步骤:
创建Python脚本文件,以.py结尾
# -*- coding: utf-8 -*-
# 这是注释,第一个Python程序
print("Hello World")
name="唐伯虎"
print(name)
注:如果脚本中有中文,可能会报错,需要在文件的第一行添加一个特殊的注释
运行脚本
python hello.py
直接执行脚本
在Linux和Mac中可以直接执行.py脚本文件,方法:
在文件的第一行添加一个特殊的注释:#!/usr/bin/env python3
为文件添加执行权限:chmod a+x hello.py
直接执行脚本文件:./hello.py
3. 使用IDE工具
PyCharm,JetBrain公司出口
使用步骤:
创建包
包中必须存在一个__init__.py文件,用于标识这是一个包
创建Python脚本
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = "汤小洋"
# 输出,使用print()
print("hello world")
name = "alice"
print(name)
4. 基本使用
输入和输出
使用print()
使用input()
注释:
单行注释,以#开头
多行注释,使用三对单引号或三对双引号
编码规范:
不要在行尾加分号
大小写敏感
适应添加空格、空行,使代码布局更优雅、美观、合理
使用缩进来表示代码块
三、Python基础
1. 变量和数据类型
变量:
定义变量时不需要指定变量的类型,直接为变量赋值即可
变量名要符合命名规范
数据类型:整型、浮点型、字符串、布尔、空值等
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = "汤小洋"
"""
数据类型:整型、浮点型、字符串、布尔、空值等
"""
# 整型int
a = 3454566666666666666
print(a)
print(type(a))
# 浮点型float
b = 12.5
print(b, type(b))
# 字符串str,定义字符串可以使用单引号或双引号(推荐用单引号)
c = "ccc"
d = "ddd"
print(c, type(c))
print("张三说:"今晚吃鸡吗?"")
# 字符串有多行时可以使用三对单引号,表示多行内容
e = """
welcome
to
itany
"""
print(e)
print(type(e))
# 布尔bool,取值:True、False
f = True
print(f, type(f))
g = 5 < 3
print(g)
print(5 + False) # True表示1,False表示0
# 空值 NoneType
h = None
print(h, type(h))
2. 字符串
类型转换
# 将字符串转换数值
a = "25"
b = int(a)
print(type(a), type(b))
c = "12.5"
d = float(c)
print(type(c), type(d))
# 将数值转换为字符串
print("hello " + str(25)) # 数值类型不能直接和字符中进行拼接,需要进行类型转换
字符串常用方法
string = " hello world "
print(string.islower())
print(string.isupper())
print(string.capitalize())
print(string.index("llo"))
print(string)
print(string.strip()) # 类似于java中的trim
print(len(string)) # 调用len()函数获取长度
切片
name = "tom cruise"
print(name[0])
print(name[4], name[len(name) - 1], name[-1])
print(name[1:5]) # 获取索引为[1,5)的字符
print(name[:5]) # 表示从头获取
print(name[2:]) # 表示获取到末尾
print(name[1:8:2]) # 索引为[1,8)的字符,每两个取一个
print(name[::2]) # 所有字符,每两个取一个
格式化
# 格式化字符串,在字符串中指定占位符
# 方式1:使用%运算符,%s表示任意字符,%d表示整数,%f表示浮点数
name = "tomaaaa"
age = 20
height = 180.5
print("大家好,我叫" + name + ",年龄:" + str(age) + ",身高:" + str(height))
print("大家好,我叫%2.4s,年龄:%d,身高:%.2f" % (name, age, height)) # 2.4s表示字符串长度为2-4位,.2f表示保留两位小数
print("当前时间:%d年-%02d月-%d日" % (2018, 5, 14)) # 指定月份为两位,不足两位则补0
# 方式2:使用format()方法,使用{}表示占位符
print("大家好,我叫{0},年龄:{1},身高:{2:.2f}".format(name, age, height))
print("大家好,我叫{name},年龄:{age},身高:{height}".format(age=age, name=name, height=height))
# 方式3:在字符串前面添加一个f,使用{变量名}来嵌入变量
print(f"大家好,我叫{name},年龄:{age},身高:{height}")
3. 运算符
算术运算符、比较运算符、赋值运算符、逻辑运算符、位运算符、条件运算符、成员运算符、身份运算符
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = "汤小洋"
"""
Python中支持的运算符:
1.算术运算符
+ - * / % // **
不支持自增++和自减--
2.比较运算符
> < >= <= == !=或<>
3.赋值运算符
= += -= *= /+ %= **=
4.逻辑运算符
and or not
5.条件运算符,也称三目运算符
语法:条件为真时的结果 if 条件 else 条件为假时的结果
6.位运算符
与& 或| 非~ 异或^ 左移<< 右移>>
7.成员运算符
in
not in
8.身份运算符
is
is not
"""
# 1.算术运算符
print(3 + 5)
print(3 * 5)
print(30 * "-") # 乘法可以用于字符串
print(5 % 3)
print(5 / 3) # 除法,有小数
print(5 // 3) # 除法,取整
print(2 ** 3) # 幂
print(pow(2, 3))
i = 5
i = i + 1
print(i)
print("*" * 80)
# 2.比较运算符
j = 5
print(j > 2)
print(10 > j > 1) # 支持此写法
print("abc" > "acd") # 可以用于字符串的比较,比较的是字符串的Unicode编码
# 3.赋值运算符
a = 10
a += 5 # 等价于a= a+5
print(a)
# 4.逻辑运算符
print(True and False)
print(5 > 2 or 4 < 1)
print(not 5 > 2)
x = 0 # 0 表示False,非0表示True
y = 8
print(x and y) # 如果x为True,则返回y;否则返回x
print(x or y) # 如果x为True,则返回x;否则返回y
print(not x) # 如果x为True,则返回False,否则返回True
# 5.条件运算符,也称三目运算符
print("aaa" if 5 < 2 else "bbb")
# 6.位运算符
a = 5 # 00000101
b = 8 # 00001000
print(a & b) # 两位都是1才为1,否则为0
print(a | b) # 只要有一位为1,则为1,否则为0
print(~a) # 如果为1,则为0,如果为0,则为1
print(a ^ b) # 如果两位相同,则为0,不同为1
print(b >> 2) # 二进制的所有位都向右移2位
# 7.成员运算符
c = [3, 5, 12, 15, 7, 2]
d = 5
print(d not in c)
# 8.身份运算符
m = [1, 3, 5, 7]
n = [1, 3, 5, 7]
x = n
print(m is n)
print(x is n)
"""
is 和 == 的区别
is 判断两个变量是否引用同一个对象
== 判断两个变量的值是否相等
"""
print(m == n)
4. 列表和元组
列表list是一种有序的集合,用来存储多个值,可以向列表中添加或删除元素
元组tuple与list很类似,也是用来存储多个值,但tuple中的元素只能在定义时初始化,初始化后就无法再修改
总结:列表list和元组tuple都是Python内置的一种集合,一个可变的,一个是不可变的
# ---列表list
# 定义列表,使用[]
names = ["tom", "jack", "alice", "mike"]
print(names)
print(type(names))
# 获取/设置元素
print(names[1], names[:3])
names[0] = "lucy"
print(names)
# 追加元素
names.append("zhangsan")
# 在指定位置插入元素
names.insert(1, "lisi")
# 删除元素
names.remove("jack")
# 弹出元素
print(names.pop(0))
# 获取元素个数
print(len(names))
# 可以存储不同类型的数据
names.append(25) # 不建议
names.append(True)
print(names)
print("-" * 80)
# ------元组tuple
# 定义元组,使用()
nums = (3, 8, 13, 25, 38, 250)
print(nums)
print(type(nums))
print(nums[2], nums[-1])
print(nums[1:3])
# 解构赋值
# a = nums[0]
# b = nums[1]
# c = nums[2]
# d = nums[3]
# e = nums[4]
# f = nums[5]
a, b, c, d, e, f = nums
print(a, b, c, d, e, f)
5. 条件判断
根据条件进行判断,从而执行不同的操作
使用if...elif...else语句
6. 循环
重复性的执行某个操作,称为循环
两种:
while循环
for...in循环
# ----while循环
# 计算1到100的和
i = 1
sum = 0
while i <= 100:
sum += i
i += 1
print(sum)
# ----for...in循环
names = ["tom", "jack", "alice", "mike"]
for name in names:
print(name, end=",")
print()
# 使用range()函数生成一个序列
for i in range(1, 100, 2): # 生成一个[1,100)的整数序列,步长为2
print(i, end=",")
print()
# 计算1到100的和
sum = 0
for i in range(1, 101):
sum += i
print(sum)
break和continue关键字
7. 字典和集合
dict全称dictionary,使用键-值(key-value)存储数据,在其他语言中一般称为map
set是无序的,不允许重复
# ----字典
# 定义dict,使用大括号{},与js中的json很类似
scores = {"tom": 98, "jack": 100, "alice": 60}
print(scores)
print(type(scores))
# 获取
print(scores["jack"])
print(scores.get("alice"))
# 添加/设置
scores["lucy"] = 89
scores["tom"] = 100
# 弹出(删除)
print(scores.pop("tom"))
# 判断是否存在指定的key
print("alice" in scores)
print(scores)
# 遍历
print(scores.keys())
print(scores.values())
print(scores.items())
for k in scores.keys():
print(k, scores[k])
print("-" * 80)
for v in scores.values():
print(v)
print("-" * 80)
for k, v in scores.items():
print(k, v)
print("-" * 80)
# -----set集合
# 定义set,使用大括号{}
# s = {3, 12, 5, 7, 34, 12, 3}
nums = [4, 23, 1, 23, 4, 23]
s = set(nums) # 调用set()函数将list转换为set,去除重复值
print(s)
print(type(s))
# 添加
s.add(666)
s.add(1)
# 删除
s.remove(1)
print(s)
# 遍历
for i in s:
print(i)
四、函数
函数是实现特定功能的代码段的封装,在需要时可以多次调用函数来实现该功能
1. 内置函数
Python内置了许多非常有用的函数,可以直接调用
2. 自定义函数
语法:
def 函数名(形参1,形参2,...):
函数体
注意:
函数名可以包含数字、字母、下划线,但不能以数字开头
如果函数有返回值,使用return关键字
定义函数后函数中的代码并不会执行,需要调用函数才会执行
# 定义函数,使用def
def calc(num1, num2): # 必选参数,也称为位置参数,不能省略
res = num1 + num2
return res
# print(calc(3, 5)) # 调用函数
# 参数类型检查
def my_abs(x):
# 可以为函数添加文档注释,也称为文档字符串doc string
"""
计算绝对值
:param x: 参数
:return: 返回x的绝对值
"""
# 对参数类型进行检查
if not isinstance(x, (int, float)):
raise TypeError("参数类型不正确,只能为数值类型") # 抛出异常
if x >= 0:
return x
else:
return -x
# print(my_abs("aaa"))
# print(help(my_abs))
# 默认参数,即有默认值的参数
def my_pow(x, y=2):
if y == 0:
return 1
res = x
for i in range(y - 1):
res *= x
return res
# print(my_pow(5))
# 可变参数,使用*号,表示参数个数是可变的
def my_sum(x, *y):
print(x)
print(y) # 接收到的实际上是一个tuple
# my_sum(3, 5, 8, 12, 4)
# 不建议下面的这种写法,建议将必选参数放在最前面
def my_sum2(*y, x):
print(y)
print(x)
# my_sum2(12, 4, 2, 7, x=9) # 必选参数在后面时需要指定参数名
# 对于可变参数,可以直接传入list或tuple,只需要在参数前添加一个*
nums = [12, 4, 2, 64, 23, 9]
# my_sum(4, nums[0], nums[1], nums[2], nums[3], nums[4], nums[5])
# my_sum(4, *nums)
# 关键字参数,使用**,也表示参数个数是可变的,但传递的是带名称的参数
def f1(x, **y):
print(x)
print(y) # 接收到的实际上一个dict
# f1(3, a=5, b=9, c=18)
# 对于关键字参数,可以直接传入一个dict,只需要在参数前添加**
user = {"id": 1001, "name": "tom", "age": 18}
# f1(4, id=user["id"], name=user["name"], age=user["age"])
# f1(4, **user)
# 命名关键字参数,限制关键字参数的名字,使用*分隔,*号后面的参数表示命名关键字参数
def f2(x, *, name, age):
print(x)
print(name)
print(age)
# f2(4, name="alice", age=20)
# 接收任意参数
def f3(*args, **kwargs):
print(args)
print(kwargs)
f3(1, 43, "aaa", name="alice", age=20)
# 空函数,表示以后再实现
def empty():
pass # 使用pass
# 函数的返回值,返回多个值
def f1():
name = "tom"
age = 20
sex = "male"
return name, age, sex
# print(f1()) # 返回值实际上是一个tuple
a, b, c = f1()
# print(a, b, c)
# 函数的返回值,返回一个函数,即将函数作为返回值
def f2(x):
print(111)
z = 6
def f3(y):
print(x * y + z) # 内部函数使用了外部函数的参数或局部变量,称为闭包
return f3
# fn = f2(3)
# fn(5)
# 递归函数:一个函数在内部调用自身,这个函数就是递归函数
# 计算x的y次方,如计算2的5次方
def calc(x, y):
# 常规方式
# if y == 0:
# return 1
# i = 1
# res = x
# while i < y:
# res *= x
# i += 1
# return res
# 递归方式
# 2*2*2*2*2=2*(2*2*2*2)=2*(2*(2*2*2))=
if y == 0:
return 1
else:
return x * calc(x, y - 1) # 不停的调用自己,递归太深可能会抛出栈溢出异常
print(calc(2, 99999999999999))
3. 变量作用域和命名空间
"""
变量作用域scope:指的是变量生效的区域
两种作用域:
1.全局作用域
函数以外的区域都是全局作用域
在全局作用域中定义的变量,都是全局变量
2.函数作用域,也称为局部作用域
函数内的区域,每调用一次函数就会创建一个新的函数作用域
在函数作用域中定义的变量,都是局部变量
变量的查找顺序:
先在当前作用域中查找,如果没有则向上一级作用域中查找,直到查找全局作用域,如果还是没有,则报错
"""
a = 5 # 全局变量
if True:
c = 5 # 全局变量,在Python中没有块级作用域
def fn():
b = 8 # 局部变量
print("函数内部:a=", a)
print("函数内部:b=", b)
print("函数内部:c=", c)
fn()
print("函数外部:a=", a)
# print("函数外部:b=", b)
print("函数外部:c=", c)
x = 1
def f1():
x = 2
def f2():
x = 3
print(x)
print("-" * 80)
# global关键字
def fn2():
# a = 10 # 在函数中为变量赋值时,默认都是为局部变量赋值
# 如果希望在函数中修改全局变量,要使用global关键字来声明变量
global a
a = 10
print("函数内部:a=", a)
fn2()
print("函数外部:a=", a)
print("*" * 80)
"""
命名空间namespace:指的是变量存储的位置,每一个变量都要存储在指定的命名空间中
每个作用域都有一个对应的命名空间
全局命名空间,用来存储全局变量;函数命名空间,用来存储函数中的变量
命名空间实际上就是一个字典dict,是一个专门用来存储变量的字典
"""
# locals() 获取当前作用域的命名空间
scope = locals() # 在全局作用域中调用locals(),获取的就是全局命名空间
print(scope)
print(type(scope))
# 通过scope操作命名空间中的变量(不建议)
print(scope["a"])
scope["c"] = 666
scope["z"] = "tom"
print(scope["c"])
print(scope["z"])
# print(z)
print("*" * 80)
def fn3():
a = 888
scope = locals() # 在函数中调用locals(),获取到的是函数命名空间
scope["b"] = 222
print(scope)
print(scope["b"])
# globals() 可以在任意位置获取全局命名空间
global_scope = globals()
print(global_scope)
print(global_scope["a"])
fn3()
4. 高级特性
迭代和列表生成式
# 导入模块
import collections
"""
迭代:也称为遍历,循环获取每一个元素
"""
for i in ["tom", "jack", "alice"]:
print(i, end=" ")
print()
for i in ("tom", "jack", "alice"):
print(i, end=" ")
print()
for i in {"name": "tom", "age": 18, "sex": "male"}.keys():
print(i, end=" ")
print()
for k, v in {"name": "tom", "age": 18, "sex": "male"}.items():
print(k, v)
for i in "hello":
print(i)
# 判断对象是否是可迭代的
print(isinstance("hello", collections.Iterable))
# 获取索引和值
# 方式1:自己获取索引
names = ["tom", "jack", "alice"]
for i in range(len(names)):
print(i, names[i])
# 方式2:使用enumerate()函数,转换为索引-元素对
print(enumerate(names))
print(isinstance(enumerate(names), collections.Iterable))
for k, v in enumerate(names):
print(k, v)
print("-" * 80)
"""
列表生成式:用来创建list的生成式
"""
# 生成[0,99]的list
# nums = range(0, 100)
nums = list(range(0, 100)) # 转换为list
# print(nums, type(nums))
# print(isinstance(range(0, 100), collections.Iterable))
# for i in range(0, 100):
# print(i)
# 生成一个包含[1,100]之间所有3的倍数的list
# 方式1
# lst = []
# for i in range(1, 101):
# if i % 3 == 0:
# lst.append(i)
# 方式2
lst = [i for i in range(1, 101) if i % 3 == 0] # 等价于a = list(range(1, 101))
print(lst)
迭代器和生成器
"""
迭代器iterator:用来访问集合元素的一种方式,可以记住迭代的位置
"""
nums = [3, 8, 12, 54, 2, 7]
it = iter(nums) # 调用iter()函数创建迭代器
print(type(it))
print(next(it)) # 调用next()函数获取迭代器的下一个元素
print(next(it)) # 只能往前不能后退
# 使用for...in循环遍历迭代器
for i in it:
print(i)
"""
生成器generator:在循环过程中依次计算获取值的对象(节省空间、效率高)
创建生成器的方式:
方式1:把一个列表生成式的[]改成()
方式2:在函数中使用yield关键字,此时该函数就变成一个生成器函数
"""
# 方式1:把一个列表生成式的[]改成()
generator = (i for i in range(1, 100))
print(type(generator)) # generator类型
# 获取生成器的下一个值
print(next(generator)) # 获取时才生成值,类似于Oracle中sequence
print(next(generator))
print(next(generator))
# 使用for...in循环遍历生成器
for i in generator:
print(i)
print("-" * 80)
# 方式2:在函数中使用yield关键字,此时该函数就变成一个生成器函数
def gen():
print("one")
yield 13
print("two")
yield 8
print("three")
yield 25
print("four")
yield 38
# 生成器函数与普通函数的执行流程不一样:
# 普通函数是顺序执行,执行到最后一行或遇到return时结束
# 生成器函数是在每次调用next()时执行,遇到yield语句就返回,下一次调用next()时会从上次返回的yield语句处继续执行
g = gen() # generator类型
print(type(g))
print(next(g))
print(next(g))
# 使用for...in循环遍历生成器
for i in g:
print(i)
高阶函数
"""
高阶函数:一个函数接收另一个函数作为参数,这种函数称为高阶函数
"""
nums = [12, -4, 3, -23, 65, 1, -234, 22]
# 定义一个函数,用来检查数字是否大于5
def f1(x):
if x > 5:
return True
return False
# 自定义高阶函数,用来过滤列表中的元素
def fn(fun, lst):
"""
将列表中所有符合条件的元素筛选出来,返回一个新列表
:param fun: 条件函数
:param lst: 要进行筛选的列表
:return: 返回新列表
"""
new_list = []
for i in lst:
if fun(i):
new_list.append(i)
return new_list
nums1 = fn(f1, nums)
print(nums1)
def f2(x):
return x % 2 == 0
print(fn(f2, nums))
# 内置高阶函数 filter(),用于过滤序列
nums2 = filter(f1, nums)
print(list(nums2))
# 内置高阶函数 map(),用于处理序列
def f3(x):
return x * x
nums3 = map(f3, nums)
print(list(nums3))
# 内置高阶函数 sorted(),用于排序
print(sorted(nums))
print(sorted(nums,key=abs))
匿名函数和装饰器
"""
匿名函数:没有名字的函数,使用lambda关键字
"""
nums = [12, 4, 32, 5, 23, 7]
# def fn(x):
# return x * 2 + 1
nums_new = list(map(lambda x: x * 2 + 1, nums))
print(nums_new)
# 将匿名函数赋给变量(不建议)
a = lambda x: x + 1
print(a(2))
print("-" * 80)
"""
装饰器:在代码运行期间动态增加功能,称为装饰器Decoration,类似于AOP
"""
# 定义一个装饰器,为函数添加打印日志的功能
def log(fn):
def wrapper(*args, **kwargs):
print("开始执行%s()函数。。。" % fn.__name__)
res = fn(*args, **kwargs)
print("执行%s()函数结束。。。" % fn.__name__)
return res
return wrapper # 返回装饰函数
@log
def even(lst):
for i in lst:
if i % 2 == 0:
print(i)
@log
def calc(num1, num2):
res = num1 + num2
return res
even([12, 34, 2, 5, 34, 21])
print(calc(3, 5))
五、面向对象
1. 定义类
语法:
class 类名:
类中成员
类中的成员:实例属性、实例方法、类属性、类方法、静态方法等
# 定义一个类,使用class关键字
class Student:
# pass
# 类属性:直接在类中定义的属性,可以通过类或实例对象来访问
hobby = "吃饭"
# 实例方法:将self作为第一个参数的方法
def say_hi(self): # self表示当前类的实例,类似于java中的this
print("Hi:" + self.name)
def say_hello(self, username="无名氏"):
print("Hello:" + username)
# 类方法:使用@classmethod修饰的方法,将cls作为第一个参数
@classmethod
def show(cls, msg): # cls表示当前类
print(msg, cls.hobby)
# 静态方法:使用@staticmethod修饰的方法,没有任何必选参数,不需要将cls作为第一个参数
@staticmethod
def show2(msg):
print(msg, Student.hobby)
# 创建类的对象
stu1 = Student() # 创建Student类的一个实例
stu2 = Student()
print(stu1, type(stu1))
print(stu2, type(stu2))
a = 3
print(a, type(a))
b = int(5) # 创建int类的一个实例
c = str("hello") # 创建str类的一个实例
print(b, type(b))
# 为对象绑定属性
stu1.name = "tom" # 实例属性,通过实例对象添加的属性
stu1.age = 20
stu2.name = "alice"
stu2.sex = "female"
stu2.height = 180.5
print(stu1.name, stu1.age)
print(stu2.name, stu2.sex, stu2.height)
# 访问实例方法
stu1.say_hi() # 调用方法时无需传递self,由解析器调用时将对象作为self自动传入
stu2.say_hi()
stu1.say_hello("张三")
stu2.say_hello()
# 访问类属性
print(Student.hobby)
stu1.hobby = "睡觉" # 为stu1添加了一个实例属性,并不会改变类属性hobby的值
print(stu1.hobby)
print(stu2.hobby) # 如果当前实例没有hobby属性,则会向上查找类属性hobby
# 访问类方法
Student.show("hello") # 调用方法时无需传递cls
stu1.show("Hello")
Student.show2("您好")
stu2.show2("你好")
2. 构造方法
__init__() 构造方法,在创建对象时会自动调用,可以用来初始化对象的属性
class Student:
# 构造方法(函数),不支持重载
def __init__(self, name, age):
print("创建对象,执行构造方法。。。")
self.name = name
self.age = age
# 实例方法
def show(self):
print("姓名:%s,年龄:%d" % (self.name, self.age))
stu1 = Student("tom", 18)
print(stu1.name, stu1.age)
stu1.show()
3. 封装、继承、多态
封装:隐藏对象中一些不希望被外部所访问到的属性,保证数据的安全
class Student:
# 定义私有属性
__age = 18 # 以两个下划线开头,表示对象的隐藏属性,只能在类内部访问
# 提供getter/setter方法
def get_age(self):
return self.__age
def set_age(self, age):
# 判断数据是否有效
if 0 < age < 100:
self.__age = age
else:
self.__age = 18
stu1 = Student()
# print(stu1.__age) # 在类外部无法访问私有属性
stu1.set_age(28)
print(stu1.get_age())
# 其实Python会把私有属性转为 _类名__属性名(强烈不建议)
print(stu1._Student__age)
继承:使一个类能够获取到其他类中的属性和方法
# 定义一个Person类,父类(超类、基类)
class Person(object): # 如果省略了父类,则默认父类为object
def __init__(self, name):
self.name = name
def run(self):
print("person:" + self.name + "正在奔跑。。。")
# 定义一个Student类,子类
class Student(Person): # 继承自Person
def __init__(self, name, email):
# 调用父类的构造方法
# Person.__init__(name) # 方式1:直接指定父类的构造方法
super().__init__(name) # 方式2:使用super,推荐
self.email = email
# 定义子类特有的方法
def study(self):
print("student:" + self.name + "正在学习。。。")
def show(self):
print("姓名:%s,邮箱:%s" % (self.name, self.email))
# 重写父类的方法
def run(self):
# super().run() # 调用父类的方法
print("student:" + self.name + "正在奔跑。。。。")
stu = Student("tom", "[email protected]")
stu.run() # 调用子类重写后的方法
stu.study()
stu.show()
# 判断一个对象是否是指定类的实例,即判断对象的类型
print(isinstance(stu, Student))
print(isinstance(stu, Person))
# 判断一个类是否是指定类的子类
print(issubclass(Student, Person))
print(issubclass(Student, object))
# object类是所有类的根类,默认所有类都继承自object
print(stu.__doc__)
print(stu.__dict__)
多继承
class A:
def a(self):
print("a")
class B:
def b(self):
print("b")
class C(A, B): # 继承多个父类,以逗号隔开
def c(self):
print("c")
c = C()
c.a()
c.b()
c.c()
# 类的特殊属性 __bases__ 可以用来获取当前类的所有父类
print(C.__bases__)
多态:多种形态
class Animal:
def __init__(self, name):
self.name = name
def cry(self):
print("动物在叫。。。。")
class Dog(Animal):
def __init__(self, name, age):
super().__init__(name)
self.age = age
def cry(self):
print("狗在叫。。。。汪汪汪")
class Cat(Animal):
def __init__(self, name, sex):
super().__init__(name)
self.sex = sex
def cry(self):
print("猫在叫。。。喵喵喵")
# 一个对象可以以不同的形式去呈现,就是多态
def play(animal):
print(animal.name)
animal.cry()
dog = Dog("旺财", 2)
cat = Cat("猫咪", "公")
play(dog)
play(cat)
4. 魔术方法
在类中可以定义一些特殊的方法,称为魔术方法
特点:
都是以双下划线开头,以双下划线结尾
不需要手动调用,在特定时机会自动执行
# 定义一个类
class Person(object):
def __init__(self, name, age):
print("__init__")
self.name = name
self.age = age
# 将对象转换为字符串时调用,类似于java中的toString()
def __str__(self):
return "Person [name=%s, age=%d]" % (self.name, self.age)
# 在对象使用len()函数时调用
def __len__(self):
return len(self.name)
# 在对象使用repr()函数时调用
def __repr__(self):
return "hello person"
# 将对象转换为bool类型时调用
def __bool__(self):
return self.age > 18
# 在对象进行大于比较时调用
def __gt__(self, other): # self表示当前对象,other表示要比较的对象
return self.age > other.age
p1 = Person("唐伯虎", 20)
p2 = Person("秋香", 18)
print(p1)
print(len(p1))
print(repr(p1))
print(bool(p1))
if p1:
print(p1.name, "已成年")
else:
print(p1.name, "未成年")
print(p1 > p2)
六、模块
1. 简介
模块化是指将一个程序分解为一个个的模块module,通过组合模块来搭建出一个完整的程序
优点:便于团队开发、方便维护、代码复用
在Python中一个.py文件就是一个模块,创建模块实际上就是创建一个.py文件,可以被其他模块导入并使用
注意:
自定义模块时要注意命名规范,使用小写,不要使用中文、特殊字符等
不要与内置模块冲突
2. 使用模块
导入模块的两种方式:
方式1:import 包名.模块名 [ as 别名]
方式2:from 包名 import 模块名
from 包名.模块名 import 变量|函数|类
导入模块的代码可以放在任意位置,但一般都放在程序的开头
# 方式1
# import py04_模块.mymodule
# print(py04_模块.mymodule.a) # 调用模块中的变量
# print(py04_模块.mymodule.plus(3, 5))
# import py04_模块.mymodule as m
# print(m.plus(3, 5))
# 方式2
# from py04_模块 import mymodule
# print(mymodule.b)
# print(mymodule.minus(8, 2))
from py04_模块.mymodule import b, plus, Calculator
# from py04_模块.mymodule import * # 不建议
# print(b)
# print(plus(2, 5))
# print(Calculator.sum(3, 12, 5))
"""
__name__属性是模块的内置属性,每个模块中都有该属性
当该.py文件是主执行文件,直接被执行时,其值为__main__
当该.py文件是被调用,导入执行时,其值为模块名
"""
# print(__name__)
# 程序入门,类似于Java中的main()方法,只在当直接调用该文件时才会执行,用来执行测试
if __name__ == "__main__":
print(Calculator.sum(1, 2, 3))
3. Python标准库
Python提供了一个强大的标准库,内置了许多非常有用的模块,可以直接使用(标准库是随Python一起安装)
常用的内置模块:
sys:获取Python解析的信息
os:对操作系统进行访问,主要是对目录或文件进行操作
math:数学运算
random:生成随机数
datetime:处理日期和时间,提供了多个类
time:处理时间
import sys
import os
import math
import random
from datetime import datetime, timedelta
import time
print(sys.version) # Python版本
print(sys.platform) # 系统平台
print(sys.argv) # 命令行参数
print(sys.path) # 模块搜索路径,包含了Python解析器查找模块的搜索路径
print(sys.modules) # 显示当前程序中引入的所有模块
print(sys.getdefaultencoding()) # 默认字符集
# sys.exit("程序退出") # 退出解析器
print("---------------------------------")
print(os.name) # 操作系统的类型
print(os.environ["path"]) # 系统的环境变量
print(os.getcwd()) # 当前的目录
print(os.listdir("d:/")) # 列出指定目录中的内容
# os.system("ping www.baidu.com") # 执行系统命令
print(os.path.exists("d:/soft")) # 判断路径是否存在
print("---------------------------------")
print(math.pi)
print(math.ceil(3.4))
print(math.floor(3.4))
print(math.pow(2, 3))
print(math.trunc(2.6)) # 截尾取整
print(round(2.6))
print(round(3.1415925, 3)) # 四舍五入,保留三位小数
print("---------------------------------")
print(random.random()) # 返回[0,1)之间的随机浮点数
print(random.randint(1, 101)) # 返回[1,100]之间的随机整数
print(random.sample([1, 21, 54, 23, 6, 2], 2)) # 从数组中返回随机两个元素
print("---------------------------------")
print(datetime.now(), type(datetime.now())) # 返回当前时间
print(datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")) # 将datetime转换为指定格式的str
print(datetime.strftime(datetime.now(), "%Y{0}%m{1}%d{2} %H:%M:%S").format("年", "月", "日"))
print(datetime.strptime("2018-2-14", "%Y-%m-%d")) # 将str转换为datetime
print("明天:", datetime.now() + timedelta(days=1)) # timedelta表示两个时间之间的时间差,可以用来进行日间的加减操作
print("前一秒:", datetime.now() - timedelta(seconds=1))
print("---------------------------------")
print(time.time()) # 返回当前时间的时间戳
print(int(time.time())) # 秒级时间戳
print(int(time.time() * 1000)) # 毫秒时间戳
time.sleep(5) # 休眠5秒
print(1111)
4. 第三方模块
Python社区提供了大量的第三方模块,使用方式与标准库类似
安装第三方模块:
使用包管理工具pip(随Python一起安装的)
pip install 模块名
使用PyCharm来安装
Settings——>Project——>Project Interpreter
报错:AttributeError: module "pip" has no attribute "main"
解决:找到PyCharm安装目录下的helpers/packaging_tool.py文件,替换其中的do_install和do_uninstall函数
pyecharts是一个用于Echarts图表的类库,便于在Python中根据数据生成可视化的图表
Echarts是百度开源的一个数据可视化JS库,主要用来进行数据可视化。
安装pyecharts库
新版本的pyecharts默认不带地图文件,如果需要使用地图,需要自行安装地图文件包
七、异常处理和IO操作
1. 异常处理
语法:
try:
可能出现异常的代码
except:
出现异常后要执行的操作
else:
不出现异常时执行的操作
finally:
无论是否出现异常都必须要执行的操作
try:
print("try...")
a = 5 / int("abc")
# except: # 捕获所有异常
# except ZeroDivisionError as e: # 捕获ZeroDivisionError异常,获取到异常对象
except (ZeroDivisionError, ValueError, Exception) as e: # 捕获多种异常
print("出现异常啦", e)
else:
print("没有异常时执行")
finally:
print("finally...")
# 自定义异常,继承自Exception(Exception类是所有异常类的父类)
class UsernameExistsException(Exception):
pass
def fn(username):
if username == "admin" or username == "tom":
raise UsernameExistsException("用户名已存在") # 使用raise抛出异常
else:
print("ok")
fn(input("请输入用户名:"))
2. IO操作
文件操作
"""
读写模式:
r 读模式
w 写模式(覆盖)
a 追加模式
r+ 读写模式
b 二进制模式
"""
# ----读取文件
try:
f = open("itany.txt", mode="r", encoding="utf-8") # 打开一个文件,返回一个对象,这个对象就代表着当前打开的文件
print(f.read()) # 一次性读取所有内容
except FileNotFoundError as e:
print("文件找不到:", e)
finally:
if f:
f.close() # 文件操作后一定要关闭
print("-" * 80)
# 简写,使用with...as语句,会自动调用close()
with open("itany.txt", mode="r", encoding="utf-8") as f:
# print(f.read())
# print(f.read(3)) # 每次读取3个字符
# print(f.read(3))
# print(f.readline().strip()) # 每次读取一行
# print(f.readline())
lines = f.readlines() # 一次性读取所有行,返回list
# print(lines)
for line in lines:
print(line.strip())
print("-" * 80)
# ----写文件
with open("itany.txt", mode="a", encoding="utf-8") as f:
f.write("xxx ")
f.write("yyy")
print("-" * 80)
# ----读写二进制文件
with open("baidu.png", mode="rb") as f:
with open("itany.png", mode="wb") as out:
out.write(f.read())
print("拷贝成功")
文件操作模块
import os
impor