变量是计算机存储数据的内存空间,因为计算机能够处理不一样的数据,不一样的数据就要定义不一样的数据类型。python的数据类型不少,还能够自定义数据类型,经常使用的通常数据类型有如下几种:html
0b10
表示十进制2,八进制:0o10
表示十进制8,十进制:10
,十六进制:0x10
表示十进制16"
或'
括起来的字符,好比:"hello, world"。'''
)/双引号("""
)括起来1 != 2
""、[]、{}
)和None
和0
表示False,反之为True计算机的函数实质上就是一段有特定功能的代码,使用函数能够有效的减小代码的耦合度,同时提升代码的可读性和易维护性。python
计算机的函数和数学的函数有必定的类似性:git
python 的函数使用def
关键词定义,须要写上函数名称,而参数值和返回值须要根据需求考虑是否填写。
如:github
def foo(num):
return num + 1
前面说过,参数就至关于数学函数的自变量,主要是一些在函数体中用到的值,python的参数能够指定默认的参数。markdown
def pow(num, count=2):
"""计算多少次方"""
return num ** count
if __name__ == "__main__":
print(pow(2)) # 4
print(pow(2, 3)) # 8
上面的函数的count参数即指定了默认参数count=2
,对于某些对于参数不肯定的函数还可使用不定长参数,其方式通常为*args
或**kwargs
,这两个参数接收的值的类型分别为list
和dict
。数据结构
def foo(*args, **kwargs):
for a in args:
print(a)
for k, v in kwargs.items():
print(k, v)
if __name__ == "__main__":
foo(1, 2, 3, **{"a": 4, "b": 5, "c": 6}, d=7)
须要注意的是:在传入参数时,能够根据函数参数的位置传参,也能够根据根据参数的关键字传参。两者能够结合使用,但位置参数必定要在关键字参数以前。
好比对于def foo(a, b, c)
来讲,既能够foo(1, 2, 3)
也能够foo(b=2, a=1, c=3)
还能够foo(1, c=3, b=2)
但不能foo(c=3, 1, 2)
。app
使用返回值须要用到一个关键词return
,一个函数的返回值能够是一个或多个值,也能够是一个函数。dom
因为python没有函数重载的概念,因此假如定义了相同函数名的函数时,前一个函数会被后一个函数所覆盖:python2.7
def foo():
print("foo1")
def foo():
print("foo2")
在平常的开发过程当中,假如是一我的开发的话能够为不一样的函数取不一样的名字,但假如是多人开发的话就有可能使用相同的函数名。多人开发时一般使用模块(module)开发,在使用时可使用import关键字导入某个指定的模块。
m1.py
:函数
def foo():
print("foo1")
m2.py
:
def foo():
print("foo2")
在使用时:
import m1
import m2
# 使用
m1.foo()
m2.foo()
须要注意的是:导入模块时会将模块的内容执行一遍,假如不想这样的话,可使用一个判断语句,使代码主动执行时运行,而不是导入时也运行。
def foo():
print("foo")
if __name__ == "___main__":
foo()
__name__
是Python中一个隐含的变量它表明了模块的名字,只有被Python解释器直接执行的模块的名字才是__main__。
做用域就至关于一个变量可使用的范围,该做用域的变量只能本做用域和子做用域可用。有了做用域这个概念就有了全局变量和局部变量这二者变量,全局变量即声明在全局做用域中的变量,而局部变量则不是声明在全局的变量,通常来讲是一些函数内部声明的变量。
n = 2 # 全局变量
def foo():
m = 3 # 局部变量
根据python的规则,变量会优先找本做用域的,假如找不到会依次往外找,直至找到,当找不到时就会报错。
age = 19
def main():
print(age)
main()
但假如要修改外部做用域的变量时,必须使用global
和nonlocal
这两个关键字声明一下,不然报错。由于python会认为修改的这个动做实际上是声明,也就是说python没有朝外找变量,假如使用变量在声明变量以前的话,就会报错:UnboundLocalError: local variable 'xxx' referenced before assignment
。
# 这是错误的示范
age = 18
def main():
print(age)
age = 20
main()
print(age)
正确的方法:
age = 18
def main():
global age
print(age)
age = 20
main()
print(age)
若是咱们但愿函数内部的函数可以修改嵌套做用域中的变量,可使用nonlocal
关键字来指示变量来自于嵌套做用域。
2. nonlocal
def test1():
count = 0
def test2():
nonlocal count
count += 1
return count
return test2()
print(test1())
实现计算求最大公约数和最小公倍数的函数。
几个整数中公有的约数,叫作这几个数的公约数;其中最大的一个,叫作这几个数的最大公约数。例如:十二、16的公约数有一、二、4,其中最大的一个是4,4是12与16的最大公约数。
实现判断一个数是否是素数的函数
# 第一题 求最大公约数和最小公倍数
def gcd(x, y):
"""最大公约数"""
(x, y) = (y, x) if x > y else (x, y)
for i in range(x, 0, -1):
if x % i == 0 and y % i == 0:
return i
def lcm(x, y):
"""最小公倍数"""
return x * y // gcd(x, y)
# 第二题
def is_prime(num):
"""判断一个数是否是素数"""
for factor in range(2, int(num ** 0.5) + 1):
if num % factor == 0:
return False
return True if num != 1 else False
字符串实质上就是由字符组成的有序序列。前面说过字符串是以引号括起来的,引号里面的内容可使用\
进行转义,使通常的字符特殊化,如:"\n"
表示换行,"\\"
表示反斜杠\
,除此以外转义符还能够跟八进制(\141
)、十六进制(\x61
)和Unicode编码。
一些经常使用的转义符
字符 | 含义 |
---|---|
\ |
在行尾时是续行符 |
\\ |
反斜杠符号 |
\' |
单引号 |
\" |
双引号 |
\a |
响铃 |
\b |
退格 |
\e |
转义 |
\000 |
空 |
\n |
换行 |
\v |
纵向制表符 |
\t |
横向制表符 |
\r |
回车 |
\f |
换页 |
除了转义之外,字符串还有不少使用方法。
s = "hello, world"
print(s[1:4])
如上所述,切片实质上就是拿中括号写成[开头:结尾:步长]
的形式(步长能够省略,且默认为一),把须要截取的一部份内容取出来,不过须要注意的是:切片里面的数不能超过要切片的范围,python的索引以0开始。假如要取开头([:n]
)或结尾([n:]
)的话,能够空着。
"".xxx()
的形式调用。s = "hello world"
# 大写
print(s.upper()) # HELLO WORLD
# 首字母大写
print(s.title()) # Hello World
# 小写
print(s.lower()) # hello world
# 替换
print(s.replace("world", "world!")) # hello world!
# 分割
print(s.split(" ")) # ['hello', 'world']
# join
print(" ".join(["hello", "world"])) # hello world
# 两边去空
print(" hello world ".strip()) # hello world
# 查找
# 找的是第一个的位置,用rfind能够找最后一个
print(s.find("l")) # 2
# print(s.index("t")) # 找不着时会报错
# 判断开头、结尾
print(s.startswith("hello")) # True
print(s.endswith("ld")) # True
列表也是python的一种经常使用的数据结构,上面例子中split
方法的结果就是一个列表。列表由一个个元素组成,各个元素的类型能够各不相同,与字符同样,列表能够切片、也有一些特定的方法,不同的是,列表能够直接经过索引对元素进行修改,而字符串则不能够。
fruits_list = ["apple", "pear", "peach", "banana"]
print(fruits_list[1:]) # ['pear', 'peach', 'banana']
# 修改值
fruits_list[2] = "orange" # ['apple', 'pear', 'orange', 'banana']
# 追加
fruits_list.append("pear") # ['apple', 'pear', 'orange', 'banana', 'pear']
# 插入
# 第一个参数是位置,第二个参数是要插入的元素
fruits_list.insert(0, "cherry")
# ['cherry', 'apple', 'pear', 'orange', 'banana', 'pear']
# 迭代添加一个列表
fruits_list.extend(["watermelon", "lemon"])
# ['cherry', 'apple', 'pear', 'orange', 'banana', 'pear', 'watermelon', 'lemon']
# 删除
# 按索引位置删除
fruits_list.pop(0)
# ['apple', 'pear', 'orange', 'banana', 'pear', 'watermelon', 'lemon']
# 删列表中的第一个指定值
fruits_list.remove("pear")
# ['apple', 'orange', 'banana', 'pear', 'watermelon', 'lemon']
# 排序
# 能够跟匿名函数lambda:fruits_list.sort(key=lambda x: len(x))
fruits_list.sort()
# ['apple', 'banana', 'lemon', 'orange', 'pear', 'watermelon']
# 查找
# 第一个指定值的位置
print(fruits_list.index("pear")) # 4
# 清空
fruits_list.clear() # []
元组是一种相似于列表的数据结构,它以小括号()
括起来为一个元组,元组的元素一样能够是任意的。可是须要注意的是,元组的元素并不能被改变,这一种特性这某些场合中适用,如某些重要的数据、不容许改变的类属性(__slots__
)和函数的多返回值。因为元组不能被修改,因此咱们只须要关注其定义和使用便可。
# 定义元组
fruits_tuple = ("apple", "pear", "peach", "banana")
# 也可使用tuple从其余可迭代数据转换过来
fruits_tuple = tuple(["apple", "pear", "banana", "peach", "banana"])
print(fruits_tuple)
# 遍历
for f in fruits_tuple:
print(f)
# 计数
print(fruits_tuple.count("banana")) # 2
# 查找
print(fruits_tuple.index("banana")) # 2
元组在内存上比列表更小,换句话说使用元组能够节省内存,使用sys.getziseof
函数能够返回该对象的字节数。
import sys
print(sys.getsizeof(("apple", "pear", "peach", "banana"))) # 72
print(sys.getsizeof(["apple", "pear", "peach", "banana"])) # 88
字典是由一个个键值对组成的数据结构,它以大括号({}
)括起来为一个数据,通常的形式为:{"key": "value}
。须要注意的是,字典的键不能重复,也就是说,假如再次给已经存在的键赋值时,原来的值会被替换;并且键是能够被哈希的数据,通常来讲,python不可变的内置类型均可以被哈希,而列表和字典是可变的,不可被哈希,因此不能做为集合的元素。。
data = {
"name": "lczmx",
"age": 18,
"address": "xxx",
}
# 获取
# 1. 使用中括号,相似于索引的方法,假如没有该键的话会报错
print(data["name"]) # lczmx
# 2. 使用get方法,没有该键时,返回另外一个参数
print(data.get("name", "none")) # lczmx
# 3. 获取键值对
for k, v in data.items():
print(f"key: {k} value: {v}")
# 4. 获取键或值
for k in data.keys():
print(f"key: {k}")
for v in data.values():
print("value: %s" % v)
# 更新
# 1. update
data.update({"score": 99, "student": True}) # 写法一
data.update(score=99, student=True) # 写法二
# {'name': 'lczmx', 'age': 18, 'address': 'xxx', 'score': 99, 'student': True}
# 2. fromkeys
# 将一个可迭代的数据的元素做为键,为多个键建立统一的值
# 注意,这是dict的方法
d2 = dict.fromkeys(["a", "b", "c"], "123")
print(d2) # {'a': '123', 'b': '123', 'c': '123'}
# 3. setdefault
# 存在取对应的值,不存在则新增键值对
print(data.setdefault("name", "lczmx")) # lczmx
# 删除
# 1. 随机删除,返回被删除的键值对
print(data.popitem()) # ('student', True)
# 2. 删除键对应的值,不存在时返回的二个参数
print(data.pop("name", "already delete")) # lczmx
# 3. 清空
data.clear()
print(data) # {}
python的集合与数学上的集合是同样的,有交集、差集、并集、补集等操做,并且元素是惟一无序的。注意:元素的类型不可变的,准确的说:能够被哈希的数据类型可成为元素。根据集合的这些特性,通常来讲其用途通常有两个方面:1. 关系测试(相交等)、2. 去重。
fruits1 = {'cherry', 'pear', 'banana', 'watermelon', 'lemon'}
fruits2 = set(['apple', 'pear', 'banana', 'orange'])
# 添加
fruits2.add("lemon")
# 交差并集能够用方法实现,也能够用符号实现
# 交集
print(fruits1.intersection(fruits2))
print(fruits1 & fruits2)
# {'banana', 'lemon', 'pear'}
# 差集
print(fruits1.difference(fruits2))
print(fruits1 - fruits2)
# {'watermelon', 'cherry'}
# 并集
print(fruits1.union(fruits2))
print(fruits1 | fruits2)
# {'banana', 'orange', 'pear', 'cherry', 'watermelon', 'lemon', 'apple'}
# 删除
# 1. remove
# 删除指定元素,不存在则报错
fruits1.remove("banana")
# 2. discard
# 删除指定元素,不存在不报错
fruits1.discard("apple")
假如定义的时候用forzenset
定义的话,则该集合不可变。
推导式是一种构建数据的快捷方式,假如用得好能够简化代码,提升可读性。但假如滥用推导式,就有可能下降代码可读性。通常来讲,超过两个for循环的代码,就不适合用推导式了,而直接用多个循环写了。
顾名思义,即生成列表的推导式,和定义列表同样,列表推导式用中括号包裹着表达式。
假若有这样一个需求:
把num = [18, 22, 23, 50]
里面的数加一,咱们当然能够,使用一个for循环把每一个元素加一,而后放回原来的列表中。但使用列表推到式只须要一行代码便可:num = [n + 1 for n in num]
。
上面的例子只有一个循环,但假如多个循环该怎么作,若是如今有num和code两个列表:
num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]
要求他们相互组合成['A1', 'A2', 'A3', 'A4', 'A5', 'B1', 'B2', 'B3', 'B4', 'B5', 'C1', 'C2', 'C3', 'C4', 'C5', 'D1', 'D2', 'D3', 'D4', 'D5']
。
很简单:
num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]
result = [c + str(n) for c in code for n in num]
print(result)
python2.7的版本中使用列表推导式有可能有变量泄露的风险,但在python3中则没有该顾虑,能够放心使用。
虽然可使用列表推导式初始化元组等其它序列类型,可是生成器表达式是更好的选择。因为生成器遵循迭代器协议,能够在用到时才生成元素,能够减小内存开销。生成器表达式在书写上与列表推导式仅仅是把中括号换成了小括号。
好比一样是上面的那个例子:
import sys
num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]
result_list = [c + str(n) for c in code for n in num]
result_tuple = tuple([c + str(n) for c in code for n in num])
result_gen = (c + str(n) for c in code for n in num)
print(sys.getsizeof(result_list), sys.getsizeof(
result_tuple), sys.getsizeof(result_gen))
# 256 200 112
使用生成器除了能够用生成器表达式,也能够用yeild
关键字:
def gen_result():
num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]
for c in code:
for n in num:
yield c + str(n)
for i in gen_result():
print(i)
自python2.7以来,列表推导式和生成器表达式的概念就移植到了字典上(集合也同样),所以就有了字典推导式。使用字典推导式能够将可迭代的数据做为键值对构建出字典。
例子:
temp = ["A1", "B2", "C3", "D4"]
result_dict = {c: n for c, n in temp}
print(result_dict) # {'A': '1', 'B': '2', 'C': '3', 'D': '4'}
假如是由两个可迭代数据组成字典的话,可使用zip
函数:
num = ["1", "2", "3", "4"]
code = ["A", "B", "C", "D"]
result_dict = dict(zip(code, num))
print(result_dict) # {'A': '1', 'B': '2', 'C': '3', 'D': '4'}
集合推导式跟列表推导式用起来差很少,下面举个简单的例子便可:
num = ["1", "2", "3", "4"]
code = ["A", "B", "C", "D"]
result_set = {c + str(n) for c in code for n in num}
print(result_set)
# {'D3', 'C3', 'A2', 'D1', 'C1', 'C2', 'B4', 'B2', 'B3', 'C4', 'A1', 'D2', 'D4', 'A3', 'B1', 'A4'}
import time
def main():
string = "放飞你的青春,奔洒你的热情。 "
while True:
print("\r%s" % string, end="")
string = string[1:] + string[0] # 把第一个字符放到最后一个,以达到运动的效果
time.sleep(0.2)
if __name__ == '__main__':
main()
import random
def veri_code(count=4):
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
temp = ""
for _ in range(count):
temp += random.sample(chars, 1)[0]
return temp
def main():
print(veri_code())
if __name__ == '__main__':
main()
def get_suffix(filename):
if "." in filename:
return filename.split(".")[-1]
else:
return ""
def get_max(data: list):
max1 = 0 # 最大
max2 = 0 # 第二大
for d in data:
if d > max1:
max2 = max1
max1 = d
else:
if d > max2:
max2 = d
return max1, max2
def triangles():
L = [1]
while True:
yield L
L = [sum(i) for i in zip([0] + L, L + [0])] # zip和sum结合,不过要在两边加0