python入门

简单语法


  • 退出python交互模式

    exit()

  • 输出

    print()

  • 输入

    input()

a = 5
b = input('你的输入:')	#输入提示语
print("result",a+b)  	#中间会有空格隔开
print('''1
2
3''')    	#用三个单引号包裹 打印会换行
  • 空值

    None

数据类型


数值

  • 科学计数法

    1.23e9 1.23x10^9

    1.2e-5 0.000012

  • /

  • 整除

    //

  • 余数

    %

9 / 3   # 3.0
10//3  	# 3 
10%3 	# 1

布尔型

True False

  • or (a or b)

  • and (a and b)

  • not (not a)

字符型

  • 转义符

    表示换行, 表示制表符,字符 本身也要转义,所以\表示的字符就是

  • r'' 表示不转义

    print(r' ') ' '

  • 获取某字符的ASCII

    ord()

  • 获取某ASCII值的字符

    chr()

ord('a')  # 97
chr(97)   # 'a'
  • 整数编码(十六进制)
'u4e2du6587'  #'中文'
  • bytes 是以字节为单位的数据类型,用于保存和传输,可以节省空间
    bytes类型的数据用带b前缀的单引号或双引号表示
x = b'abc' 
y = b"abc"

字符方法

  • 字符型转成bytes

    encode()

  • bytes转成字符型

    decode()

'ABC'.encode('ascii')     # b'ABC'
'中文'.encode('utf-8')	# b'xe4xb8xadxe6x96x87'

b'ABC'.decode('ascii') 	  # 'ABC'
b'xe4xb8xadxe6x96x87'.decode('utf-8')  # '中文'

b'xe4xb8xadxff'.decode('utf-8', errors='ignore')  # '中'   小部分无效字节,忽略它
  • 获取字符长度

    len() 【 也可获取bytes字节数】

len('ABC')  	# 3
len(b'ABC')  	# 3
len('中文'.encode('utf-8'))  # 6
  • 字符格式化

    用 % 占位,用变量填充模板

    %d -- 整数

    %s -- 字符串

    %f -- 浮点数

    %x -- 十六进制整数

用了占位符还想输%,可以用%%来转义

'Hello, %s' % 'world'   #  'Hello, world'
'name: %s,age: %d' % ('李白',32)   # 'name: 李白,age: 32'
'%2d-%02d' % (3, 1)   #  '3-01'
'%.2f' % 3.1415926    #  '3.14'
'growth rate: %d %%' % 7  #'growth rate: 7 %'

format() 第二种格式化方法

'Hello, {0}, 成绩提升了 {1}%'.format('小明', 17.125)  
#'Hello, 小明, 成绩提升了 17.125%'

'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
#'Hello, 小明, 成绩提升了 17.1%'

列表类型

list 是python内置的一种数据类型
list 是一种有序的集合,可以随时添加和删除其中的元素。【也就是数组咯】

创建

students = ['李白','杜甫','白居易']

取值

len(students)  	# 3
students[0]    	# '李白'
students[2]    	# '白居易'

### 可以逆序
students[-1] 	# '白居易'
students[-2] 	# '杜甫'
  • 获取list长度

    len(list)

    len(students)	# 3
    
  • 添加元素到末尾

    list.append(value)

    students.append('小胖')
    
  • 插入元素到指定位置

    list.insert(i,value)

    students.insert(1,'小胖')
    
  • 删除list末尾元素

    list.pop()

    students.pop()	# '白居易'
    
  • 删除指定位置元素

    list.pop(i)

    students.pop(1)	# '杜甫'
    
  • 排序

    list.sort() 改变本身

    a = ['c', 'b', 'a']
    a.sort()
    a	# ['a', 'b', 'c']
    

元组类型

tuple 是另一种有序的集合,特点为一旦初始化,元素就不能重新赋值。且它也没有能操作元素的方法。

创建

ages = (16,18,30)

取值

len(ages)	# 3
ages[2]		# 30
ages[0]		# 16

特别注意

ages = ()	# 空元组
ages = (1)	# 并不是元组,而是1
ages = (1,)	# 包含一个元素的元组

字典

dict 类型,全称 dictionary,其他语言里称为 map,使用键值存储,查找速度快。

ages = {
    '李白':17,
    '杜甫':18,
    '白居易':19
}
ages['李白']	# 17

ages['李白'] = 50

ages['唐太宗']	   # 报错,不存在对应的key

ages.get('唐太宗') 	# None
ages.get('唐太宗',-1) 	# -1

####或者
'唐太宗' in ages	# False

删除元素

ages.pop('李白')

set

set 和 dict类似,也是一组key的集合,但不存储value,可以看成数学意义上的无序和无重复元素的集合。

创建一个set,需要提供一个list作为输入集合

s = set([1,2,2,3,3])
s	# {1,2,3}  重复元素会被过滤
  • 添加元素

    s.add()

    s.add(4)	# {1,2,3,4}
    s.add(4)	# {1,2,3,4} 重复添加的元素会被过滤
    
  • 删除元素

    s.remove()

    s.remove(4)	# {1,2,3}
    s.remove(4)	# 报错,不存在 4  
    
  • 交集 并集

    s1 = set([1,2,3])
    s2 = set([2,3,4])
    s1 & s2		# {2,3} 
    s1 | s2		# {1,2,3,4}
    

基本语法


注意语法的冒号

条件判断

if <条件判断1>:
    <执行1>
elif <条件判断2>:
    <执行2>
elif <条件判断3>:
    <执行3>
else:
    <执行4>

循环

names = ['李白','杜甫','白居易']
for name in names:
    print(name)
    
for i in range(100):     # 从0开始,小于100的整数
    print(i)
n = 99
while n > 0:
    print(n)
    n = n - 2

break 退出循环

continue 跳过该次循环

函数


常用函数

  • 数学函数

    abs() 绝对值

    abs(-20)	# 20
    abs(1.34)	# 1.34
    

    max() 取最大值

    max(1,1.78,-5,55.55)	# 55.55
    

    hex() 数字转十六进制字符

    hex(255)	# '0xff'
    

  • 数据类型转换

    int('123')	# 123
    int(12.34)	# 12   转整数
    
    float('12.34')	# 12.34
    float('222')	# 222.0	 转浮点数
    
    str(1.23)	# '1.23'  转字符型
    
    bool(1)		# True	 转布尔型
    
    list(range(5))	# 转列表 
    

函数定义

格式

def 函数名(参数):

def plus(x,y):
    return x+y

空函数

def fun():
    pass	# 用 pass 占位,防止报错

返回多个值

实际上是返回一个tuple,赋值操作时tuple特性会逐一赋值

def add(x,y):
    return x+1,y+1

a,b = add(4,7)
print(a,b)	# 5 8

c = add(4,7)
print(c)	# (5,8)

默认参数(可选参数)

def fun(x = 5) 提前给予默认值

def fun(x = 5):
    return x*x

fun()	# 25
fun(4)	# 16

当可选参数较多时,调用时可选择性输入

def login(name,age = 18,city = "杭州"):
	pass

login('小明',city = "常州")	# 调用时,选择性输入

可变参数(多个参数)

*形参 定义时,形参会是一个tuple来接收所有参数

def sum(*num):
    res = 0
    for i in num:
        res = res + i
    return res

sum()        # 0
sum(3,1,6)	 # 10	

*实参 调用时,允许直接使用 list 和 tuple,相当于直接赋给形参了

sum(*[1,2,3])	# 6
sum(*(2,3,6))	# 11

关键字参数

**形参 定义时,用dict接收所有参数

def func(**some):
    print(some)
    
func()	# {}
func(3)	# 报错,不接受该种形式传参
func(name = '小白',age = 18)	# {'name': '小白', 'age': 18}

####### 修改
def func(lv = 0,**some):
    print(some)
    
func()	# {}
func(3)	# {}
func(name = '小白',age = 18)	# {'name': '小白', 'age': 18}

**实参 调用时,直接使用dict传递,形参获得实参的拷贝

obj = {
    'name':'小白',
    'age':18,
}
func(**obj)	# {'name': '小白', 'age': 18}

命名关键字参数

只接收特定key的参数,用*分隔

def note(name,age,*,city,job):
    print(name,age,city,job)
    
note('小白',18,city="杭州",job='teacher')	# 小白 18 杭州 teacher
note('小白',18)	# 报错,缺少2个 keyword-only arguments

#### 修改
def note(name,age,*,city = "常州",job):
    print(name,age,city,job)
    
note('小白',18,job='teacher')	# 小白 18 杭州 teacher
note('小白',18)	# 报错,缺少1个 keyword-only arguments

参数组合

参数在定义时可以组合使用,但必须保证一定的顺序,该顺序为

必选参数 → 默认参数 → 可变参数 → 命名关键字参数 → 关键字参数

递归函数

def fact(n):
    if n == 1:
        return 1
    return n * fact(n-1)
防止栈溢出

解决递归调用栈溢出的方法是通过尾递归优化

尾递归 在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。

示例函数由于使用了乘法表达式,所以就不是尾递归了。尾递归要求只能返回一个表达式,所以,我们就需要把上一次的执行结果放到参数中传递下去。

def fact(n,result = 1):
    if n == 1:
        return result
    return fact(n-1,n*result)

不过python解释器并未对尾递归做优化,所以栈溢出还是会存在

高级特性


切片:

# 获取list或tuple指定索引范围的数据
L = [1,2,3,"haha"]
L[0:3]   # [1,2,3]  序号0开始,不包括序号3
L[:3]    # 同上
L[-2:]   # [3, 'haha']  支持倒数序号
L[-2:-1] # [3]

L[:2:2]  # [1] 前2个,每两个取一个
L[::2]   # [1,3] 所有元素,每两个取一个

复制list

L[:]  # 复制了L

字符切片

'ABCDEFG'[:3]  # 'ABC'
'ABCDEFG'[::2] # 'ACEG'

迭代:

for循环遍历

迭代list或tuple

a = [1,2,3]
for i in a:
    print(i)

迭代dict

# 迭代顺序不一定
d = {'a': 1, 'c': 2, 'b': 3}
for key in d:
    print(key)
# a
# c
# b
# 迭代 value
d = {'a': 1, 'c': 2, 'b': 3}
for value in d.values():
    print(value)
# 迭代 key & value
d = {'a': 1, 'c': 2, 'b': 3}
for k, v in d.items():
    print(k,v)
# a 1
# c 2
# b 3

迭代字符串

for ch in 'ABC':
    print(ch)
# A
# B
# C

判断是否可迭代 通过collections模块的Iterable类型判断

from collections import Iterable
isinstance('abc', Iterable) # True  str是否可迭代
isinstance([1,2,3], Iterable) # True  list是否可迭代
isinstance(123, Iterable) # False  整数是否可迭代

迭代下标 -- Python内置的enumerate函数

# enumerate
for i, value in enumerate(['A', 'B', 'C']):
    print(i, value)
# 0 A
# 1 B
# 2 C

迭代内容

for x, y in [(1, 1), [2, 4], (3, 9)]:
    print(x, y)
# 1 1
# 2 4
# 3 9
## 子 tuple 或 子 list 长度只能为 2

列表生成式:

list()

list(range(1, 11))  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

生成更复杂的列表

### 常规做法
L = []
for x in range(1, 11):
    L.append(x * x)
print(L)  
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

### 类似map的做法
[x * x for x in range(1, 11)]  
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[x * x for x in range(1, 11) if x % 2 == 0] 
# [4, 16, 36, 64, 100]  加判断
[m + n for m in 'ABC' for n in 'XYZ']  
# ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ'] 双重循环

小结: 复杂的列表生成式包含js中mapfilter方法,并且扩展性更大,可以循环dict,还可以可以双重循环,总的来说自由度更高,使用需要上点心。

生成器:

不必创建完整的list,边循环边推演获得后续元素,从而可以节约空间。这种机制被称为生成器:generator

L = [x * x for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

g = (x * x for x in range(10)) # <generator object <genexpr> at 0x000000CC0A38A518>

和列表生成器的区别就在于外层是()

获取generator的下一个元素

next(g) # 0
next(g) # 1
next(g) # 4
next(g) # 9
...

循环generator

g = (x * x for x in range(10))
for n in g:
    print(n)
# 0
# 1
# 4
# ...
# 81

generator函数

#### 普通斐波那契数列
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

fib(5)  # 1
        # 1
        # 2
        # 3
        # 5
        # 'done'
        
#### generator函数  yield关键字
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'  # 执行到这句会终止函数 但是返回值无法直接获取
    
fib(5) # <generator object fib at 0x0000003C89A1A570>

for n in fib(5):
    print(n)
# 1
# 1
# 2
# 3
# 5

generator函数的执行顺序

### 遇到 yield就中断,但依靠循环可以不断执行下去

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

a = odd()  # a赋值成一个generator对象
next(a) # 打印'step1'  返回值为1
next(a) # 打印'step2'  返回值为3
next(a) # 打印'step3'  返回值为5

小结: 生成器有两种形式,简单逻辑通过()包装即可,复杂逻辑则需要通过函数形式并配合yield关键字实现。两种方式都是为了保存某种算法,通过算法可以计算推导出每一项。

迭代器:

可直接作用于for循环的对象统称为可迭代对象:Iterable

判断对象是否可迭代

from collections import Iterable

isinstance([], Iterable)    # True
isinstance({}, Iterable)    # True
isinstance('abc', Iterable) # True
isinstance((x for x in range(10)), Iterable)    # True
isinstance(100, Iterable)   # False

可以被next()方法调用并不断返回下一个值的对象称为迭代器:Iterator

判断对象是否是迭代器对象

from collections import Iterator

isinstance([], Iterator)    # False
isinstance({}, Iterator)    # False
isinstance('abc', Iterator) # False
isinstance((x for x in range(10)), Iterator)    # True
isinstance(100, Iterator)   # False


### iter()方法可将 list、dict、str等变成迭代器对象
isinstance(iter([]), Iterator)    # True
isinstance(iter('abc'), Iterator) # True

函数式编程


高阶函数

  • map/reduce

map 接收两个参数,一个是函数,一个是Iterable,新结果作为Iterator返回

def f(x):
    return x * x
r = map(f,[1,2,3])  # <map object at 0x000000D84BDFFF28>
list(r)     # [1,4,9]  计算 Iterator,获得完整的 list

reduce 接收两个参数,一个是函数,一个是Iterable,高阶函数的参数为计算结果和下一个元素

from functools import reduce

def add(x, y):
    return x + y
r = reduce(add, [1, 2, 3])  # 6

### lambda函数
r = reduce(lambda x, y : x + y,[1,2,3])  # 6
  • filter

filter 接收一个函数,一个Iterable,返回Iterator

def is_odd(n):
    return n % 2 == 1
    
r = filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
list(r) # [1, 5, 9, 15]

####返回所有素数
## 算法 埃氏筛法

def origin():  # 初始序列
    n = 2
    while True:
        yield n
        n = n + 1
        
def not_divisible(n): 
    return lambda x: x % n != 0   # 表示不能整除

def primes():   # 素数序列
    arr = origin()
    while True:
        n = next(arr) # 返回序列的第一个数
        yield n 
        arr = filter(not_divisible(n),arr) # 筛除部分非素数
  • sorted

sorted 接收一个Iterable,接收一个key函数,返回一个list

a = [36, 5, -12, 9, -21]
sorted(a)  # [-21, -12, 5, 9, 36]
print(a)   # [36, 5, -12, 9, -21]  不会改变原列表

####添加 key函数
sorted(a, key=abs)   # [5, 9, -12, -21, 36]
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower) 
# ['about', 'bob', 'Credit', 'Zoo']
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower, reverse=True) 
# ['Zoo', 'Credit', 'bob', 'about']   反向

####自定义 key函数
def by_name(t):
    return t[0].lower()
sorted([('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)],key=by_name)
# [('Adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88)]

### 特别注意
sorted("bacdge")  # ['a', 'b', 'c', 'd', 'e', 'g']

返回函数(闭包)

即函数作为返回值,也可以称为函数生成器

### python的作用域貌似有点严格
def createCounter():
    n = 0
    def counter():
        nonlocal n  # nonlocal 关键字   用来声明变量需要向上一层寻找
        n = n + 1
        return n

    return counter

counterA = createCounter()
print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5

### 引用类型不需要 nonlocal关键字
def createCounter():
    arr = [0]
    def counter():
        arr[0] = arr[0] + 1
        return arr[0]

    return counter

匿名函数(lambda)

没有 return,不能遍历,不能使用 if: else:分支

add = lambda x,y: x + y   # 带参数

add = lambda x,y: x + y if y >= 0 else x  # 三元判断符

def add(x, y):
    return lambda: x + y  # 无参数

装饰器

增强某函数的功能,但又不希望修改原函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

### 定义一个函数做装饰器 接收一个函数 并返回一个函数
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)  # 打印函数名称
        return func(*args, **kw)
    return wrapper
    
# '@'关键字  在函数定义处设置装饰器
@log     
def now():
    print('today')

now()  
# call now():
# today

@log放在函数定义处等价于 now = log(now)

装饰器可传入参数 (等于多包了一层函数)

#### 装饰器传入参数
def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
        
    return decorator

@log('execute')
def now():
    print('today')
    
now()
# execute now()
# today

### 等价于  now = log('execute')(now)

最后的问题 now.__name__wrapper

#### 解决最终问题
### functools.wraps

import functools

def log(func):
    @functools.wraps(func)  ### 关键句  用装饰器包装 wrapper 函数
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

偏函数(Partial function)

提前给定参数的函数生成器

int('10')  # 10
int('10',base=2) # 2

### 偏函数  2进制转10进制
import functools
int2 = functools.partial(int,base=2) # 原函数 和 给定参数
int2('10') # 2

小结
偏函数可以固定参数,用来简化函数调用,在原函数分支较多,或者参数过多的情况下,可以用偏函数优化。

原文地址:https://www.cnblogs.com/grey-zhou/p/10444574.html