前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python基础(一)

Python基础(一)

作者头像
haifeiWu
发布2018-09-11 10:23:19
6720
发布2018-09-11 10:23:19
举报
文章被收录于专栏:haifeiWu与他朋友们的专栏

此为学习Python的基础语法笔记,如有错误,欢迎评论纠正。

Python基础

Python的语法比较简单,采用缩进方式。

以#开头的语句是注释,解释器会忽略掉注释。其他每一行都是一个语句,当语句以冒号:结尾时,缩进的语句视为代码块。

Python程序是大小写敏感的,如果写错了大小写,程序会报错。

数据类型和变量

数据类型
  • 整数
  • 浮点数
  • 字符串 (Python还允许用r’’表示’’内部的字符串默认不转义)
  • 布尔值 (True, False)
  • 空值 None
变量
  • 变量 ( a = 1 )
  • 常量 ( 没有固定语法,通常用全部大写的变量名表示常量 )
字符串和编码

Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符。

代码语言:javascript
复制
>>> ord('A')
65
>>> chr(66)
'B'

Python对bytes类型的数据用带b前缀的单引号或双引号表示:

代码语言:javascript
复制
x = b'ABC'

以Unicode表示的str通过encode()方法可以编码为指定的bytes

代码语言:javascript
复制
>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'

在bytes中,无法显示为ASCII字符的字节,用\x##显示。

反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法。

代码语言:javascript
复制
>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'

要计算str包含多少个字符,可以用len()函数

代码语言:javascript
复制
>>> len('ABC')
3
>>> len('中文')
2

len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数

代码语言:javascript
复制
>>> len(b'ABC')
3
>>> len('中文'.encode('utf-8'))
6

在Python中,采用的格式化方式和C语言是一致的,用%实现。

代码语言:javascript
复制
>>> '%2d-%02d' % (3, 1)
' 3-01'
>>> '%.2f' % 3.1415926
'3.14'

常见的占位符有:

header 1 | header 2

| — | — |

| %d | 整数 |

%f | 浮点数

%s | 字符串

%x | 十六进制整数

list和tuple

list
代码语言:javascript
复制
>>> classmates = ['Michael', 'Bob', 'Tracy']
  • 增加元素:classmates.append(‘Adam’)
  • 插入元素到指定位置:classmates.insert(1, ‘Jack’)
  • 删除末尾元素:classmates.pop()
  • 删除指定位置元素:classmates.pop(1)
  • 替换元素:classmates1 = ‘Sarah’
tuple

tuple和list非常类似,但是tuple一旦初始化就不能修改。

代码语言:javascript
复制
>>> classmates = ('Michael', 'Bob', 'Tracy')

条件判断

代码语言:javascript
复制
age = 3
if age >= 18:
    print('adult')
elif age >= 6:
    print('teenager')
else:
    print('kid')

循环

for in循环
代码语言:javascript
复制
names = ['Michael', 'Bob', 'Tracy']
for name in names:
    print(name)
while循环
代码语言:javascript
复制
sum = 0
n = 99
while n > 0:
    sum = sum + n
    n = n - 2
print(sum)
break及continue

dict和set

dict

Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。

代码语言:javascript
复制
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95

和list比较,dict有以下几个特点:

  1. 查找和插入的速度极快,不会随着key的增加而变慢;
  2. 需要占用大量的内存,内存浪费多。
set

set和dict类似,也是一组key的集合,但不存储value。key不能重复。

代码语言:javascript
复制
>>> s = set([1, 2, 3])
>>> s
{1, 2, 3}
  • add(key)
  • remove(key)

函数

在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。  

函数体内部可以用return随时返回函数结果。  

函数执行完毕也没有return语句时,自动return None。  

函数可以同时返回多个值,但其实就是一个tuple。  

代码语言:javascript
复制
def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x

支持默认参数、可变参数和关键字参数。

函数的参数

默认参数
代码语言:javascript
复制
def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)
enroll('Adam', 'M', city='Tianjin')

定义默认参数要牢记一点:默认参数必须指向不变对象!

可变参数
代码语言:javascript
复制
def calc(*numbers)
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
calc(1,2)
关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。

代码语言:javascript
复制
def person(name, age, **kw):
    if 'city' in kw:
        # 有city参数
        pass
    if 'job' in kw:
        # 有job参数
        pass
    print('name:', name, 'age:', age, 'other:', kw)
    
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}
>>> extra = {'city': 'Beijing', 'job': 'Engineer'}
>>> person('Jack', 24, **extra)
name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
命名关键字参数

命名关键字参数需要一个特殊分隔符后面的参数被视为命名关键字参数。

代码语言:javascript
复制
def person(name, age, *,city, job)
    print(name,age,city,job)
    
>>>person('jack',24,city='Beijing',job='Engineer')
Jack 24 Beijing Engineer
参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

代码语言:javascript
复制
def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
    
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}

高级特性

切片

代码语言:javascript
复制
L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

取前3个元素:

代码语言:javascript
复制
>>>L[:3]

所有数,每5个取一个

代码语言:javascript
复制
>>>L[::5]

复制一个List

代码语言:javascript
复制
>>>L[:]

list、tuple、字符串都可以使用。

迭代

当我们使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行,而我们不太关心该对象究竟是list还是其他数据类型。通过collections模块的Iterable类型判断:

代码语言:javascript
复制
>>>from collections import iterable
>>>isinstance('abc',Iterable)
True
>>>isinstance([1,2,3].iterable)
Ture
>>>isinstance(123,iterable)
False

默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()。

代码语言:javascript
复制
>>>for x,y in [(1,1),(2,4),(3,9)]
...    print(x,y)
...
1 1
2 4
3 9

列表生成式

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。

代码语言:javascript
复制
>>>[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']
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

生成器

要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成()。

代码语言:javascript
复制
>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x1022ef630>

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值。

定义generator的另一种方法:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:

代码语言:javascript
复制
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

代码语言:javascript
复制
>>> g = fib(6)
>>> while True:
...     try:
...         x = next(g)
...         print('g:', x)
...     except StopIteration as e:
...         print('Generator return value:', e.value)
...         break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:

  1. 一类是集合数据类型,如list、tuple、dict、set、str等;
  2. 一类是generator,包括生成器和带yield的generator function。

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

而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。

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

把list、dict、str等Iterable变成Iterator可以使用iter()函数:

代码语言:javascript
复制
>>> from collections import Iterator
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True

函数式编程

高阶函数

把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。

  1. 变量可以指向函数。
  2. 函数名也是变量。
  3. 传入函数
map/reduce

map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。

代码语言:javascript
复制
>>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
['1', '2', '3', '4', '5', '6', '7', '8', '9']

reduce把一个函数作用在一个序列x1, x2, x3, …上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:

代码语言:javascript
复制
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

一个str2int的函数就是:

代码语言:javascript
复制
from functools import reduce
def str2int(s)
    def fn(x,y)
        return x * 10 + y
    def char2num(s)
        return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
    return reduce(fn,map(char2num,s))

//用lambda函数进一步简化成:
def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]
def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))
filter

Python内建的filter()函数用于过滤序列。

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

代码语言:javascript
复制
def not_empty(s):
    return s and s.strip()

list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
# 结果: ['A', 'B', 'C']
sorted

Python内置的sorted()函数就可以对list进行排序:

代码语言:javascript
复制
>>> sorted([36, 5, -12, 9, -21])
[-21, -12, 5, 9, 36]

此外,sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序,例如按绝对值大小排序:

代码语言:javascript
复制
>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

返回函数

高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。

代码语言:javascript
复制
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

匿名函数

当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。

代码语言:javascript
复制
>>> list(map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
[1, 4, 9, 16, 25, 36, 49, 64, 81]

装饰器

现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

代码语言:javascript
复制
def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper

@log
def now():
    print('2015-3-25')
    
>>> now()
call now():
2015-3-25

把@log放到now()函数的定义处,相当于执行了语句:

代码语言:javascript
复制
now = log(now)

如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:

代码语言:javascript
复制
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('2015-3-25')
    
>>> now()
execute now():
2015-3-25

和两层嵌套的decorator相比,3层嵌套的效果是这样的:

代码语言:javascript
复制
>>> now = log('execute')(now)

因为返回的那个wrapper()函数名字就是’wrapper’,所以,需要把原始函数的name等属性复制到wrapper()函数中,否则,有些依赖函数签名的代码执行就会出错。

不需要编写wrapper.name = func.name这样的代码,Python内置的functools.wraps就是干这个事的,所以,一个完整的decorator的写法如下:

代码语言:javascript
复制
import functools

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

偏函数

Python的functools模块提供了很多有用的功能,其中一个就是偏函数(Partial function)。要注意,这里的偏函数和数学意义上的偏函数不一样。

functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:

代码语言:javascript
复制
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64

最后,创建偏函数时,实际上可以接收函数对象、*args和**kw这3个参数。

当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。

作 者:ChanghuiN

原文链接:https://cloud.tencent.com/developer/article/1333344

版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Python基础
    • 数据类型和变量
      • 数据类型
      • 变量
      • 字符串和编码
    • list和tuple
      • list
      • tuple
    • 条件判断
      • 循环
        • for in循环
        • while循环
        • break及continue
      • dict和set
        • dict
        • set
    • 函数
      • 函数的参数
        • 默认参数
        • 可变参数
        • 关键字参数
        • 命名关键字参数
        • 参数组合
    • 高级特性
      • 切片
        • 迭代
          • 列表生成式
            • 生成器
              • 迭代器
              • 函数式编程
                • 高阶函数
                  • map/reduce
                  • filter
                  • sorted
                • 返回函数
                  • 匿名函数
                    • 装饰器
                      • 偏函数
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档