[TOC]
记录一下自己的python学习之旅,入门书籍为《python编程:从入门到实践》,运行环境为python3.6.3。也有一定的编程基础,对于一些通用的语法不再赘述,本篇主要记录一下python一些不同于java的基本语法。
书写格式
- 一句代码的结束以换行为标志,不需要分号。
- 建议每级缩进都使用四个空格。
- 建议每行不超过80字符,建议注释的行长不超过72字符。
- 不同的逻辑之间可用一个空行隔开。
- 代码块不需要大括号,python根据缩进来判断代码行与前一个代码行的关系。
- python变量和函数命名习惯采用小写,可用下划线隔开,不像java采用驼峰命名法。
- 在条件测试的格式设置方面,建议在诸如== 、>= 和<= 等比较运算符两边各添加一个空格。
基本数据类型
- Number(数字)
- int(整型)
- long(长整型)
- float(浮点型)
- complex(复数)
- String(字符串)
- List(列表)
- Tuplc(元组)
- Dictionary(字典)
常用计算符号
- +,加号
- -,减号
- *,乘号
- /,除号
- %,取余
- //,整除
- **,乘方
变量
变量不需要声明。
message = "Hello Python"
print(message)
字符串
- 字符串可以用双引号,也可以用单引号,这样可以方便的在字符串中使用引号,当然也可以像java一下通过转义字符表示引号。
- 下标从左到右从0开始,从右到左从-1开始,-1表示最后一个字符。
- 截取字符串使用 str[开始下标 :结束下标]。
- python中的字符串也封装了许多的基本操作方法,比如大小写转换,去首尾空格等,可以在使用过程中慢慢去熟悉。
message = " Hello world "
print(message.title()) # 首字母大写
print(message.lower()) # 转换小写
print(message.upper()) # 转换大写
print(message.count("o")) # 字符计数
print(message.strip()) # 去首尾空格
print(message.lstrip()) # 去开头空格
print(message.rstrip()) # 去结尾空格
print(message.__len__()) # 字符串长度
数字
- 数字和字符串不能直接拼接。
print("Hello " + 213) # TypeError: must be str, not int
print("Hello " + str(213)) # Hello 213
整数
- python中可以用 ** 表示乘方运算
- python3中两个整数相除时,会得到真实的结果,而python2中只会得到整数部分,这与java类似(3/2=1)。
print(2 ** 3) # 8
print(3 / 2) # 1.5
print(4 / 3) # 1.3333333333333333
注释
- python中注释用#来表示。
列表
有序集合,用[]表示。类似于但又不同于java中的数组、集合。
- python中的列表不要求数据类型相同,及不用类型的数据可以放到同一个列表中,姑且简单理解为List
- 有序集合,因此支持按索引访问,索引从0开始。不同的是python还支持反向索引,-1代表最后一个数据,-2代表倒数第二个,依次类推。
names = ["Allen", "Toto", 123]
print(names) # ['Allen', 'Toto', 123]
print(names[1]) # Toto
print(names[-1]) # 123
- 修改元素:类似于java数组,直接通过索引赋值修改。
- 添加元素:提供append和insert方法,分别用于在列表末尾追加和在指定索引位置插入新元素。也可以通过extend方法直接在末尾追加一个列表。
- 删除元素:提供pop和remove方法,分别用于删除指定索引和指定值的元素。也可用del语句来删除。注意remove方法只是删除一个元素,如果列表中有多个相同元素,可以通过循环删除。
names = ["Allen", "Toto", 123]
print(names) # ['Allen', 'Toto', 123]
names[2] = 456
print(names) # ['Allen', 'Toto', 456]
names.append(True)
print(names) # ['Allen', 'Toto', 456, True]
names.insert(1, 123)
print(names) # ['Allen', 123, 'Toto', 456, True]
del names[-1]
print(names) # ['Allen', 123, 'Toto', 456]
test = names.pop(-1)
print(names) # ['Allen', 123, 'Toto']
print(test) # 456
names.remove("Allen")
print(names) # [123, 'Toto']
- 排序:注意只有所有元素为相同类型的列表可以排序。可以通过列表的sort方法或者sorted函数来进行排序,其中sort会改变原列表,sorted不会改变原列表。也可以通过参数来控制顺序。
names = ["Allen", "Toto", "Lili"]
names.sort()
print(names) # ['Allen', 'Lili', 'Toto']
names.sort(reverse=True)
print(names) # ['Toto', 'Lili', 'Allen']
print(sorted(names)) # ['Allen', 'Lili', 'Toto']
print(names) # ['Toto', 'Lili', 'Allen']
- 遍历:通过for循环进行遍历,类似于java中的foreach语句,仅仅是写法不同。
names = ["Allen", "Toto", "Lili"]
for item in names: # 注意最后有个冒号,代码块需要缩进
print(item)
如果需要对索引和值同时迭代,可以使用python内置的enumerate函数:
names = ["Allen", "Toto", "Lili"]
for index,item in enumerate(names): # 注意最后有个冒号,代码块需要缩进
print(index,item)
- 数值列表:python使用range函数可以很方便的创建一个数值列表,结果符合编程中最常见的差一行为,比如range(1,6),实际生成的为1到5这五个数字。
nums = list(range(1, 6)) # 创建数值列表
print(nums) # [1, 2, 3, 4, 5]
# range还支持步数
nums = list(range(1, 6, 2)) # [1, 3, 5]
print(nums)
- 列表解析:将for循环和创建新元素的代码合并成一行,并自动附加新元素。下面两种写法是等价的。
nums = list()
for item in range(1, 6):
nums.append(item ** item)
print(nums) # [1, 4, 27, 256, 3125]
# 列表解析的格式为[表达式 + for循环]
nums = [item ** item for item in range(1, 6)]
print(nums) # [1, 4, 27, 256, 3125]
- 切片:即截取列表的部分相邻元素。通过指定要截取的第一个和最后一个索引来进行切片,并得到一个新的列表。依然符合差一行为。
nums = list(range(1, 11))
# 实际上是从索引1到4
print(nums[1:5]) # [2, 3, 4, 5]
# 没有指定开始索引会默认从0开始 没指定结束索引会默认到列表最后一个元素结束
print(nums[:5]) # [1, 2, 3, 4, 5]
print(nums[5:]) # [6, 7, 8, 9, 10]
print(nums[:]) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# 也支持负索引
print(nums[-3:]) # [8, 9, 10]
- 列表的复制:列表的复制可以直接使用切片的方式,不能直接将变量赋值给另一个变量,这和java中的概念(list.addAll)是相同的。
# 这样相当于将变量nums和nums_2都关联到了同一个列表,不是复制
nums = [1, 2, 3]
nums_2 = nums
nums_2.append(4)
print(nums_2) # [1, 2, 3, 4]
print(nums) # [1, 2, 3, 4]
# 可以用切片来达到复制列表的目的
nums = [1, 2, 3]
nums_2 = nums[:]
nums_2.append(4)
print(nums_2) # [1, 2, 3, 4]
print(nums) # [1, 2, 3]
元组
python将不可修改的值称为不可变的,而不可变的列表称为元组。
- 元组使用圆括号标识,除了元素不可变之外,可以向操作列表一样遍历、操作元组。
# 元组:不可变的列表
nums = (1, 2, 3)
print(nums) # (1, 2, 3)
print(nums[-2:]) # (2, 3)
if语句
语法同大多数编程语言,仅仅是书写格式不同。
- 条件判断:
- 区分大小写,如果不想区分大小写判断是否相等,可以先都转换成小写再判断。
- 支持==、>、<、>=、<=、!=判断。
- 多个判断条件可以使用and和or关键字,效果等于java中的&&和||。
- 判断元素是否包含在某个列表中时,可以使用in和not in关键字。
- python在进行条件判断时,会将非空的字符串或列表认为True,反之为False。
a = "a"
b = "A"
if a == b: # a.lower() == b.lower()
print("a == b")
elif a.lower() == b.lower():
print("a.lower() == b.lower()")
else:
print(False)
nums = [1, 2, 3]
nums_2 = [3, 4, 5]
if (3 in nums) and (3 not in nums_2): # False
print(True)
else:
print(False)
nums = []
a = "a"
if nums: # a
print("nums")
elif a:
print("a")
else:
print(False)
字典
在Python中,字典是一系列键--值对 。每个键都与一个值相关联,你可以使用键来访问与之相关联的值。与键相关联的值可以是数字、字符串、列表乃至字典。事实上,可将任何Python对象用作字典中的值。类似于java中的Map。
- python中,字典用花括号来标识,每一个键值对之间以逗号分隔。
student = {"name": "Allen", "age": 15}
- 可以通过字典的键来访问与之关联的值。
- 字典是一种动态结构,可随时在其中添加、修改键值对,只需指定字典的键即可。
- 可以通过del语句删除字典中的键值对。
student = {"name": "Allen", "age": 15}
print(student["name"]) # Allen
student["name"] = "Lili"
print(student) # {'name': 'Lili', 'age': 15}
student["address"] = "ChangSha"
print(student) # {'name': 'Lili', 'age': 15, 'address': 'ChangSha'}
del student["address"]
print(student) # {'name': 'Lili', 'age': 15}
- 可以通过for循环遍历字典的所有键、所有值或者是所有的键值对。但是不保证遍历顺序和存储顺序相同。
student = {'name': 'Lili', 'age': 15, 'address': 'ChangSha'}
for k, v in student.items():
print(str(k) + ":" + str(v))
for k in student.keys(): # 遍历字典时会默认遍历key,因此等效于 for k in student:
print(k)
for v in set(student.values()): # 如果需要去重的话,可以使用集合set,类似于列表,但每个元素都是独一无二的
print(v)
while循环
基本语法同大多数编程语言,仅书写格式不同。
nums = [1, 1, 1, 1, 2, 2, 1, 3]
while 1 in nums:
nums.remove(1)
print(nums) # [2, 2, 3]
函数
- 函数用关键词def定义,函数体依然采用缩进方式。
- 函数的说明文档用三引号注释,写在函数体的第一行。
def print_hello():
"""打招呼"""
print("Hello")
print_hello() # Hello
- 参数传递:python中实参的传递有三种方式:位置实参,关键字实参和默认值。位置实参即基于实参的顺序依次传递,这是大多数编程语言中的一种普遍做法。关键字实参通过键值对的方式传递参数,不用考虑参数的顺序。默认值即在编写函数时为形参指定一个默认值,调用函数时如果不指定实参,则使用此默认值。注意如果不指定默认值,则调用函数时必须传入该实参。
def print_hello(name, age="15"):
"""打招呼"""
print("你好,我叫" + str(name) + "," + str(age) + "岁")
print_hello("李狗蛋", "12") # 你好,我叫李狗蛋,12岁
print_hello("12", "李狗蛋") # 你好,我叫12,李狗蛋岁
print_hello(age="12", name="李狗蛋") # 你好,我叫李狗蛋,12岁
# 形参可以有默认值,相当于简化了java中的方法的多态
print_hello("李狗蛋") # 你好,我叫李狗蛋,15岁
- 返回值:python中函数可以通过关键字return返回一个值,且python是弱类型语言,无需指定返回的值的类型。
- 列表作为实参传入时,如果函数内部对该列表做了修改,则原列表也会改变,这一点同java是一样的。如果不想修改原列表,可以将列表的一个副本作为实参传入,比如使用切片。
def getList(list):
list[0] = 2
return list
a = [1, 2]
print(getList(a)) # [2, 2]
print(a) # [2, 2]
a = [1, 2]
print(getList(a[:])) # [2, 2]
print(a) # [1, 2]
- 函数可以使用 *+形参名 的形式添加任意数量的参数(相当于在函数内部,将可变参数组成了一个tuple),类似于java中的 形参名+... 符号,如果有多个不同类型的形参,这种接收任意数量参数的形参只能放在最后。
def muti(*name): # 形参名*name 中的星号让Python创建一个名为name 的空元组,并将收到的所有值都封装到这个元组中。
print(name)
muti("a") # ('a',)
muti("a", "b", "c") # ('a', 'b', 'c')
- 函数可以通过两个星号来接收任意数量的关键字实参(键值对,相当于在函数内部,将可变关键字参数组成了一个dict)。
def person(name, age, **other): # 形参名**other 中的星号让Python创建一个名为other 的空字典,并将收到的所有键值对都封装到这个字典中。
p = {"name": name, "age": age}
for k, v in other.items():
p[k] = v
print(other)
person("Allen", 15, sex="man", address="ChangSha") # {'name': 'Allen', 'age': 15, 'sex': 'man', 'address': 'ChangSha'}
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和score作为关键字参数。这种方式定义的函数如下:
def person(name, age, *, address, score):
print(name, age, address, score)
person("Allen", 15, address='Beijing', score=98)
和关键字参数 ** other不同,命名关键字参数需要一个特殊分隔符* ,*后面的参数被视为命名关键字参数。
- 在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
- 导入外部函数:要让函数是可导入的,得先创建模块。模块是扩展名为.py的文件,包含要导入到程序中的代码。导入方式:
- import module_name:导入整个模块。
- import module_name as other_name:为导入的模块起一个别名。
- from module_name import function_name:导入模块中的某个函数,function_name可以有多个,用逗号隔开,表示导入该模块的多个函数。
- from module_name import function_name as other_name:导入模块中的某个函数,并起一个别名,一般原函数名字太长或者有同名函数时使用。
- from module_name import *:导入该模块的全部函数。
注:只导入模块时,需通过module_name.function_name调用(前两种方式),导入函数时,可以直接通过函数名使用(后三种方式)。当然,有别名的情况下也可以使用别名。
类
- 通过关键字class标识,类名的首字母大写,采用驼峰命名法,可以在类名的下一行添加注释文档,用三引号标识。
- python的类有一个特殊的方法__ init__(),每次创建类的实例时都会运行这个方法,类似于java中的构造函数。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
- 形参self必不可少,还必须位于其他形参的前面。每个与类相关联的方法调用都自动传递实参self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
- 以self 为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量,我们可以将这些以self为前缀的变量称为属性。
- 以两个下划线开头可以定义类的私有方法和属性,命名格式为__private_method,self.__private_attrs。
class Person:
"""测试类"""
def __init__(self, name="Allen", age=15, sex="man"):
self.name = name
self.age = age
self.sex = sex
self.address = ""
print("person " + name + " init")
def walk(self):
print(self.name + " can walk.")
def run(self):
self.walk()
print(self.name + " can run too.")
- 继承。
class Person:
"""测试类"""
def __init__(self, name, age=15, sex="man"):
self.name = name
self.age = age
self.sex = sex
self.address = ""
print("person " + name + " init")
def walk(self):
print(self.name + " can walk.")
def run(self):
self.walk()
print(self.name + " can run too.")
person = Person("Allen") # person Allen init
person.run() # Allen can walk. Allen can run too.
class Student(Person): # Student继承于Person
def __init__(self, name): # 子类的__init__方法需要接收父类的所有参数,有默认值的可以不传,会取默认值
super().__init__(name) # 子类继承父类的所有属性和方法
def walk(self): # 重写父类方法
print("override function.")
def get_teacher(self, teacher_name): # 子类的自定义方法
print(self.name + "'s teacher is " + teacher_name)
student = Student("Allen") # person Allen init
student.get_teacher("Lili") # Allen's teacher is Lili
student.walk() # override function.
文件读写
通过open函数打开一个文件,进行读写操作,完成后通过close函数关闭文件,也可以使用with关键字,让python自己选择适时关闭文件。
def open(file, mode='r', buffering=None, encoding=None, errors=None, newline=None, closefd=True):
open函数可以接收一个mode参数,包括以下值:
- 'r' 只读方式打开 (default)
- 'w' 只写方式打开,打开文件会清空文件,再写入,文件不存在时会自动创建文件。
- 'x' 创建一个新文件并以只写方式打开
- 'a' 只写方式打开,打开文件会将写入内容拼接到文件最后,
- 'b' 字节模式
- 't' 文本模式(default)
- '+' 打开一个硬盘文件进行更新 (reading and writing)
- 'U' universal newline mode (已过时)
默认模式为"rt"。
读文件
测试文件 file_io_test:
abcdefg
hijklmn
opq
rst
uvw
xyz
- 读取整个文件
with open("file_io_test") as file: # 关键字with 在不再需要访问文件后适时将其关闭。
print(file.read()) # read()可以接收一个int参数,表示读取的字节数,传-1表示读取全部,默认值为-1
- 读取一行
with open("file_io_test") as file:
print(file.readline()) # abcdefg 行末尾有一个换行符
print(file.readline()) # hijklmn
- 读取每行,并存储到一个列表
with open("file_io_test") as file:
print(file.readlines()) # ['abcdefg\n', 'hijklmn\n', 'opq\n', 'rst\n', 'uvw\n', 'xyz']
- 逐行读取
with open("file_io_test") as file:
for line in file: # 等同于line = file.readline()
print(line)
- 是否可读
with open("file_io_test") as file:
print(file.readable()) # readable()是否可读,返回一个布尔值
写文件
with open("file_write_test", mode="w+") as file: # w换成a后可以附加到文件中,不会覆盖
file.write("456") # 写入456
print(file.readable()) # True
异常
处理异常:
def divide(a, b):
"""除法运算"""
try:
result = a / b
except ZeroDivisionError:
print("除数不能为0")
else:
print(result)
finally:
print("运行完毕")
divide(1, 0) # 除数不能为0 运行完毕
divide(1, 5) # 0.2 运行完毕
存储数据
通过json存储
import json
nums = [1, 2, 3, 4, 5]
with open("jsonTest.json", "w") as file:
json.dump(nums, file) # 写入文件,接收一个内容对象和文件对象
with open("jsonTest.json") as file:
result = json.load(file)
print(result)