参考资料:
表示注释,作用于整行
- ‘’’ ‘’’ 或者 “”” “”” 表示区间注释,在三引号之间的所有内容被注释
参考资料
入门参考
阿里云天池
https://tianchi.aliyun.com/course/308/3553
尚硅谷课程
菜鸟教程
可视化输出
https://pythontutor.com/render.html#mode=display
实战参考
《利用Python进行数据分析》
数据类型
列表
列表是有序集合,没有固定大小,能够保存任意数量任意类型的 Python 对象,语法为 [元素1, 元素2, …, 元素n]
- 列表是Python中的一个对象
- 对象(object)就是内存中专门用来存储数据的一块区域
- 之前我们学习的对象,像数值,它只能保存一个单一的数据
- 列表中可以保存多个有序的数据
- 列表是用来存储对象的对象
列表的创建
#普通创建
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
print(x, type(x))
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'] <class 'list'>
#利用range()创建列表
x = list(range(10))
print(x, type(x))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <class 'list'>
x = list(range(1, 11, 2))
print(x, type(x))
# [1, 3, 5, 7, 9] <class 'list'>
x = list(range(10, 1, -2))
print(x, type(x))
# [10, 8, 6, 4, 2] <class 'list'>
#利用推导式创建列表
x = [0] * 5
print(x, type(x))
# [0, 0, 0, 0, 0] <class 'list'>
x = [0 for i in range(5)]
print(x, type(x))
# [0, 0, 0, 0, 0] <class 'list'>
x = [i for i in range(10)]
print(x, type(x))
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <class 'list'>
x = [i for i in range(1, 10, 2)]
print(x, type(x))
# [1, 3, 5, 7, 9] <class 'list'>
x = [i for i in range(10, 1, -2)]
print(x, type(x))
# [10, 8, 6, 4, 2] <class 'list'>
x = [i ** 2 for i in range(1, 10)]
print(x, type(x))
# [1, 4, 9, 16, 25, 36, 49, 64, 81] <class 'list'>
x = [i for i in range(100) if (i % 2) != 0 and (i % 3) == 0]
print(x, type(x))
列表元素的增加
1、
list.append(obj) 在列表末尾添加新的对象,只接受一个参数,
参数可以是任何数据类型,被追加的元素在 list 中保持着原结构类型。
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.append('Thursday')
print(x)
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Thursday']
print(len(x)) # 6
此元素如果是一个 list,那么这个 list 将作为一个整体进行追加
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.append(['Thursday', 'Sunday'])
print(x)
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', ['Thursday', 'Sunday']]
print(len(x)) # 6
2、
list.extend(seq) 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.extend(['Thursday', 'Sunday'])
print(x)
# ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Thursday', 'Sunday']
print(len(x)) # 7
严格来说 append 是追加,把一个东西整体添加在列表后,
而 extend 是扩展,把一个东西里的所有元素添加在列表后
3、
list.insert(index, obj) 在编号 index 位置插入 obj。
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
x.insert(2, 'Sunday')
print(x)
# ['Monday', 'Tuesday', 'Sunday', 'Wednesday', 'Thursday', 'Friday']
print(len(x)) # 6
列表元素的获取
列表元素的删除
1、list.remove(obj) 移除列表中某个值的第一个匹配项
2、list.pop([index=-1]) 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
x = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
y = x.pop()
print(y) # Friday
y = x.pop(0)
print(y) # Monday
y = x.pop(-2)
print(y) # Wednesday
print(x) # ['Tuesday', 'Thursday']
remove 和 pop 都可以删除元素,前者是指定具体要删除的元素,后者是指定一个索引。
3、del var1[, var2 ……] 删除单个或多个对象。
# 切片
# 切片指从现有列表中,获取一个子列表
# 创建一个列表,一般创建列表时,变量的名字会使用复数
stus = ['孙悟空','猪八戒','沙和尚','唐僧','蜘蛛精','白骨精']
元组
# 元组 tuple
# 元组是一个不可变的序列
# 它的操作的方式基本上和列表是一致的
# 所以你在操作元组时,就把元组当成是一个不可变的列表就ok了
# 一般当我们希望数据不改变时,就使用元组,其余情况都使用列表
字符串
转义字符
转义字符 | 描述 |
---|---|
\\ | 反斜杠符号 |
\‘ | 单引号 |
\“ | 双引号 |
\n | 换行 |
\t | 横向制表符(TAB) |
\r | 回车 |
print('let\'s go') # let's go
print("let's go") # let's go
print('C:\\now') # C:\now
print("C:\\Program Files\\Intel\\Wifi\\Help")
# C:\Program Files\Intel\Wifi\Help
字符串切片与拼接
类似于元组具有不可修改性
从 0 开始 (和 Java 一样)
切片通常写成 start:end 这种形式,包括「start 索引」对应的元素,不包括「end索引」对应的元素。
索引值可正可负,正索引从 0 开始,从左往右;
负索引从 -1 开始,从右往左。使用负数索引时,会从最后一个元素开始计数。
最后一个元素的位置编号是 -1。
str1 = 'I Love LsgoGroup'
print(str1[:6]) # I Love
print(str1[5]) # e
print(str1[:6] + " 插入的字符串 " + str1[6:])
# I Love 插入的字符串 LsgoGroup
s = 'Python'
print(s) # Python
print(s[2:4]) # th
print(s[-5:-2]) # yth
print(s[2]) # t
print(s[-1]) # n
常用内置方法
capitalize() 将字符串的第一个字符转换为大写
str2 = 'xiaoxie'
print(str2.capitalize()) # Xiaoxie
############################
lower() 转换字符串中所有大写字符为小写。
upper() 转换字符串中的小写字母为大写。
swapcase() 将字符串中大写转换为小写,小写转换为大写。
str2 = "DAXIExiaoxie"
print(str2.lower()) # daxiexiaoxie
print(str2.upper()) # DAXIEXIAOXIE
print(str2.swapcase()) # daxieXIAOXIE
############################
count(str, beg= 0,end=len(string))
返回str在 string 里面出现的次数,如果beg或者end指定则返回指定范围内str出现的次数。
str2 = "DAXIExiaoxie"
print(str2.count('xi')) # 2
############################
find(str, beg=0, end=len(string))
检测 str 是否包含在字符串中,如果指定范围 beg 和 end,则检查是否包含在指定范围内,
如果包含,返回开始的索引值,否则返回 -1。
rfind(str, beg=0,end=len(string)) 类似于 find() 函数,不过是从右边开始查找。
str2 = "DAXIExiaoxie"
print(str2.find('xi')) # 5
print(str2.find('ix')) # -1
print(str2.rfind('xi')) # 9
字符串格式化
format 格式化函数
str8 = "{0} Love {1}".format('I', 'Lsgogroup') # 位置参数
print(str8) # I Love Lsgogroup
str8 = "{a} Love {b}".format(a='I', b='Lsgogroup') # 关键字参数
print(str8) # I Love Lsgogroup
str8 = "{0} Love {b}".format('I', b='Lsgogroup') # 位置参数要在关键字参数之前
print(str8) # I Love Lsgogroup
str8 = '{0:.2f}{1}'.format(27.658, 'GB') # 保留小数点后两位
print(str8) # 27.66GB
符 号 | 描述 |
---|---|
%c | 格式化字符及其ASCII码 |
%s | 格式化字符串,用str()方法处理对象 |
%r | 格式化字符串,用rper()方法处理对象 |
%d | 格式化整数 |
%o | 格式化无符号八进制数 |
%x | 格式化无符号十六进制数 |
%X | 格式化无符号十六进制数(大写) |
%f | 格式化浮点数字,可指定小数点后的精度 |
%e | 用科学计数法格式化浮点数 |
%E | 作用同%e,用科学计数法格式化浮点数 |
%g | 根据值的大小决定使用%f或%e |
%G | 作用同%g,根据值的大小决定使用%f或%E |
print('%c' % 97) # a
print('%c %c %c' % (97, 98, 99)) # a b c
print('%d + %d = %d' % (4, 5, 9)) # 4 + 5 = 9
print("我叫 %s 今年 %d 岁!" % ('小明', 10)) # 我叫 小明 今年 10 岁!
print('%o' % 10) # 12
print('%x' % 10) # a
print('%X' % 10) # A
print('%f' % 27.658) # 27.658000
print('%e' % 27.658) # 2.765800e+01
print('%E' % 27.658) # 2.765800E+01
print('%g' % 27.658) # 27.658
text = "I am %d years old." % 22
print("I said: %s." % text) # I said: I am 22 years old..
print("I said: %r." % text) # I said: 'I am 22 years old.'
字典
- 序列是以连续的整数为索引,与此不同的是,字典以”关键字”为索引,关键字可以是任意不可变类型,通常用字符串或数值。
- 字典是 Python 唯一的一个 映射类型,字符串、元组、列表属于序列类型。
那么如何快速判断一个数据类型 X 是不是可变类型的呢?两种方法:
- 麻烦方法:用 id(X) 函数,对 X 进行某种操作,比较操作前后的 id,如果不一样,则 X 不可变,如果一样,则 X 可变。
- 便捷方法:用 hash(X),只要不报错,证明 X 可被哈希,即不可变,反过来不可被哈希,即可变。
i = 1
print(id(i)) # 140732167000896
i = i + 2
print(id(i)) # 140732167000960
l = [1, 2]
print(id(l)) # 4300825160
l.append('Python')
print(id(l)) # 4300825160
集合
函数
函数参数
- 位置参数 (positional argument)
- 默认参数 (default argument)
- 可变参数 (variable argument)
- 关键字参数 (keyword argument)
- 命名关键字参数 (name keyword argument)
- 参数组合
类和对象
对象 = 属性 + 方法
什么是对象?
- 对象是内存中专门用来存储数据的一块区域。
- 对象中可以存放各种数据(比如:数字、布尔值、代码)
- 对象由三部分组成:
1.对象的标识(id)
2.对象的类型(type)
3.对象的值(value)
Python 的 self 相当于 C++ 的 this 指针。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
# <__main__.Test object at 0x000000BC5A351208>
# <class '__main__.Test'>
类的方法与普通的函数只有一个特别的区别 —— 它们必须有一个额外的第一个参数名称(对应于该实例,即该对象本身),按照惯例它的名称是 self。在调用方法时,我们无需明确提供与参数 self 相对应的参数。
class Ball:
def setName(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball()
a.setName("球A")
b = Ball()
b.setName("球B")
c = Ball()
c.setName("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...
# 尝试定义一个表示人的类
class Person :
# 在类的代码块中,我们可以定义变量和函数
# 在类中我们所定义的变量,将会成为所有的实例的公共属性
# 所有实例都可以访问这些变量
name = 'swk' # 公共属性,所有实例都可以访问
# 在类中也可以定义函数,类中的定义的函数,我们称为方法
# 这些方法可以通过该类的所有实例来访问
def say_hello(self) :
# 方法每次被调用时,解析器都会自动传递第一个实参
# 第一个参数,就是调用方法的对象本身,
# 如果是p1调的,则第一个参数就是p1对象
# 如果是p2调的,则第一个参数就是p2对象
# 一般我们都会将这个参数命名为self
# say_hello()这个方法,可以显示如下格式的数据:
# 你好!我是 xxx
# 在方法中不能直接访问类中的属性
print('你好!我是 %s' %self.name)
类的基本结构
class 类名([父类]) :
公共的属性...
# 对象的初始化方法
def __init__(self,...):
...
# 其他的方法
def method_1(self,...):
...
def method_2(self,...):
...
...
创建对象的流程
p1 = Person()的运行流程
1.创建一个变量
2.在内存中创建一个新对象
3.__init__(self)方法执行
4.将对象的id赋值给变量
私有变量/方法
在 Python 中定义私有变量只需要在变量名或函数名前加上“__”两个下划线,那么这个函数或变量就会为私有的了
【例子】类的私有属性实例
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
counter.count() # 2
print(counter.publicCount) # 2
# Python的私有为伪私有
print(counter._JustCounter__secretCount) # 2
print(counter.__secretCount)
# AttributeError: 'JustCounter' object has no attribute '__secretCount'
【例子】类的私有方法实例
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('老马的程序人生', 'https://blog.csdn.net/LSGO_MYP')
x.who()
# name : 老马的程序人生
# url : https://blog.csdn.net/LSGO_MYP
x.foo()
# 这是公共方法
# 这是私有方法
x.__foo()
# AttributeError: 'Site' object has no attribute '__foo'
# 使用__开头的属性,实际上依然可以在外部访问,所以这种方式我们一般不用
# 一般我们会将一些私有属性(不希望被外部访问的属性)以_开头
# 一般情况下,使用_开头的属性都是私有属性,没有特殊需要不要修改私有属性
class Person:
def __init__(self,name):
self._name = name
def get_name(self):
return self._name
def set_name(self , name):
self._name = name
p = Person('孙悟空')
print(p._name)
property装饰器
class Person:
def __init__(self,name,age):
self._name = name
self._age = age
# property装饰器,用来将一个get方法,转换为对象的属性
# 添加为property装饰器以后,我们就可以像调用属性一样使用get方法
# 使用property装饰的方法,必须和属性名是一样的
@property
def name(self):
print('get方法执行了~~~')
return self._name
# setter方法的装饰器:@属性名.setter
@name.setter
def name(self , name):
print('setter方法调用了')
self._name = name
@property
def age(self):
return self._age
@age.setter
def age(self , age):
self._age = age
p = Person('猪八戒',18)
p.name = '孙悟空'
p.age = 28
print(p.name,p.age)
魔法方法
魔法方法总是被双下划线包围,例如init。
魔法方法是面向对象的 Python 的一切,如果你不知道魔法方法,说明你还没能意识到面向对象的 Python 的强大。
魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。
魔法方法的第一个参数应为cls(类方法) 或者self(实例方法)。
- cls:代表一个类的名称
- self:代表一个实例对象的名称
init(self[, …]) 构造器,当一个实例被创建的时候调用的初始化方法
class Rectangle:
def __init__(self, x, y):
self.x = x
self.y = y
def getPeri(self):
return (self.x + self.y) * 2
def getArea(self):
return self.x * self.y
rect = Rectangle(4, 5)
print(rect.getPeri()) # 18
print(rect.getArea()) # 20
class Person :
# 在类中可以定义一些特殊方法(魔术方法)
# 特殊方法都是以__开头,__结尾的方法
# 特殊方法不需要我们自己调用,不要尝试去调用特殊方法
# 特殊方法将会在特殊的时刻自动调用
# 学习特殊方法:
# 1.特殊方法什么时候调用
# 2.特殊方法有什么作用
# 创建对象的流程
# p1 = Person()的运行流程
# 1.创建一个变量
# 2.在内存中创建一个新对象
# 3.__init__(self)方法执行
# 4.将对象的id赋值给变量
# init会在对象创建以后离开执行
# init可以用来向新创建的对象中初始化属性
# 调用类创建对象时,类后边的所有参数都会依次传递到init()中
def __init__(self,name):
# print(self)
# 通过self向新建的对象中初始化属性
self.name = name
def say_hello(self):
print('大家好,我是%s'%self.name)
# 目前来讲,对于Person类来说name是必须的,并且每一个对象中的name属性基本上都是不同
# 而我们现在是将name属性在定义为对象以后,手动添加到对象中,这种方式很容易出现错误
# 我们希望,在创建对象时,必须设置name属性,如果不设置对象将无法创建
# 并且属性的创建应该是自动完成的,而不是在创建对象以后手动完成
# p1 = Person()
# # 手动向对象添加name属性
# p1.name = '孙悟空'
# p2 = Person()
# p2.name = '猪八戒'
# p3 = Person()
# p3.name = '沙和尚'
# p3.say_hello()
p1 = Person('孙悟空')
p2 = Person('猪八戒')
p3 = Person('沙和尚')
p4 = Person('唐僧')
# p1.__init__() 不要这么做
# print(p1.name)
# print(p2.name)
# print(p3.name)
# print(p4.name)
p4.say_hello()
模块、包
# 在Python中一个py文件就是一个模块,要想创建模块,实际上就是创建一个python文件
# 注意:模块名要符号标识符的规范
# 在一个模块中引入外部模块
# ① import 模块名 (模块名,就是python文件的名字,注意不要py)
# ② import 模块名 as 模块别名
# - 可以引入同一个模块多次,但是模块的实例只会创建一个
# - import可以在程序的任意位置调用,但是一般情况下,import语句都会统一写在程序的开头
# - 在每一个模块内部都有一个__name__属性,通过这个属性可以获取到模块的名字
# - __name__属性值为 __main__的模块是主模块,一个程序中只会有一个主模块
# 主模块就是我们直接通过 python 执行的模块
import test_module as test
# print(test.__name__)
print(__name__)
模块的使用
from m import *
# print(_c)
# import xxx
# import xxx as yyy
# from xxx import yyy , zzz , fff
# from xxx import *
# from xxx import yyy as zz
# 编写测试代码,这部分代码,只要当当前文件作为主模块的时候才需要执行
# 而当模块被其他模块引入时,不需要执行的,此时我们就必须要检查当前模块是否是主模块
if __name__ == '__main__':
test()
test2()
p = Person()
print(p.name)
包 Package
# 包 Package
# 包也是一个模块
# 当我们模块中代码过多时,或者一个模块需要被分解为多个模块时,这时就需要使用到包
# 普通的模块就是一个py文件,而包是一个文件夹
# 包中必须要一个一个 __init__.py 这个文件,这个文件中可以包含有包中的主要内容
from hello import a , b
print(a.c)
print(b.d)
# __pycache__ 是模块的缓存文件
# py代码在执行前,需要被解析器先转换为机器码,然后再执行
# 所以我们在使用模块(包)时,也需要将模块的代码先转换为机器码然后再交由计算机执行
# 而为了提高程序运行的性能,python会在编译过一次以后,将代码保存到一个缓存文件中
# 这样在下次加载这个模块(包)时,就可以不再重新编译而是直接加载缓存中编译好的代码即可
工具
jupyter
Pycharm
Anaconda