zoukankan      html  css  js  c++  java
  • Python3.x 基础篇

    历史

    1990年 Python 诞生;2000年 Python 2.0 发布;2008年 Python 3.0 发布;2010年 Python 2.7 发布(最后一个2.x 版本)。

    Python的作者说,Python2.x 已经是遗产,Python3.x 是现在和未来的语言。

    语言特点

    语法简洁;跨平台;可扩展;开放源码;类库丰富。

    最典型的“编程语言两问”:

    你了解你学过的每种编程语言的特点吗?

    你能根据不同的产品需求,选用合适的编程语言吗?

    举个例子,Python 的优点之一是特别擅长数据分析,所以广泛应用于人工智能、机器学习等领域,如机器学习中 TensorFlow 的框架,就是用 Python 写的。

    但是涉及到底层的矩阵运算等等,还是要依赖于 C++ 完成,因为 C++ 的速度快,运行效率更高。

    事实上,很多公司都是这样,服务器端开发基于 Python,但底层的基础架构依赖于 C++。这就是典型的“不同需求选用不同语言”。

    版本选择

    Python最流行的发行版Anaconda

    学习网站

    Python官方文档: https://www.python.org/doc/

    iPython: https://www.ipython.org/

    jupyter notebook: http://jupyter-notebook.readthedocs.io/en/latest/

    sublime text: https://www.sublimetext.com

    PyCharm: https://www.jetbrains.com/pycharm/

    pip: https://pip.pypa.io/en/stable/installing/

    在线编程:http://www.dooccn.com/python3/

    Jupyter Notebook

    按照 Jupyter 创始人 Fernando Pérez 的说法,他最初的梦想是做一个综合 Ju (Julia)、Py (Python)和 R 三种科学运算语言的计算工具平台,所以将其命名为 Ju-Py-te-R。

    发展到现在,Jupyter 已经成为一个几乎支持所有语言,能够把软件代码、计算输出、解释文档、多媒体资源整合在一起的多功能科学运算平台。

    Stack  Overflow: https://stackoverflow.com/

    Jupyter Notebook: https://jupyter.org/

    Jupyter 官方的 Binder 平台:https://mybinder.org/

    介绍文档:https://mybinder.readthedocs.io/en/latest/index.html

    Google 提供的 Google Colab 环境介绍:https://colab.research.google.com/notebooks/welcome.ipynb

    基本数据类型

    int     整数

    float  浮点数

    bool  布尔值 True False

    str     字符串,如python, "python",如果字符串里有',则采用" "

    cindy@ubuntu:~$ python3
    Python 3.8.10 (default, Jun  2 2021, 10:49:15) 
    [GCC 9.4.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> 
    >>> type(1)
    <class 'int'>
    >>> type(2.2)
    <class 'float'>
    >>> type(True)
    <class 'bool'>
    >>> type('1')
    <class 'str'>
    >>> 
    >>> int('123')
    123
    >>> str(123)
    '123'
    >>> 
    >>> bool(123)
    True
    >>> bool(0)
    False
    >>> 
    >>> float(1)
    1.0
    >>> int(1.0)
    1
    >>> 
    View Code

    Misc

    i > 0 and i < 10
    
    i = int(s)
    print(type(i)) # i is a int
    
    import time
    time.sleep(1)

    序列

    序列指它的成员都是有序排列,并且可以通过下标偏移量访问到它的一个或几个成员。

    字符串、列表 list、元组 tuple 三种类型都属于序列。

    字符串 “abcd”

    元组 (“abc”, “def”),不可修改

    列表 [ 0, “abcd”],可修改

    序列的基本操作

    in, not in 成员关系操作符,对象[not] in 序列;

    + 连接操作符,序列 + 序列;

    * 重复操作符,序列 * 整数;

    [:] 切片操作符,序列[0:整数]

    字符串

    字符串是由独立字符组成的一个序列,是不可变的(immutable),通常包含在单引号('')双引号("")或者三引号之中(''' '''或""" """,两者一样)。

    Python 同时支持这三种表达方式,很重要的一个原因就是,这样方便你在字符串中,内嵌带引号的字符串。

    Python 的三引号字符串,则主要应用于多行字符串的情境,比如函数的注释等等。

    Python 也支持转义字符。所谓的转义字符,就是用反斜杠开头的字符串,来表示一些特定意义的字符。

    s1 = 'hello'
    s2 = "hello"
    s3 = """hello"""
    s1 == s2 == s3
    True
    
    def calculate_similarity(item1, item2):
        """
        Calculate similarity between two items
        Args:
            item1: 1st item
            item2: 2nd item
        Returns:
          similarity score between item1 and item2
        """
    
    s = 'a
    b	c'
    print(s)
    a
    b  c
    len(s)
    5

    常见的的转义字符:

    Python 中字符串的改变,通常只能通过创建新的字符串来完成。

    比如把'hello'的第一个字符'h',改为大写的'H':

    s = 'H' + s[1:]
    s = s.replace('h', 'H')

    第一种方法,是直接用大写的'H',通过加号'+'操作符,与原字符串切片操作的子字符串拼接而成新的字符串。

    第二种方法,是直接扫描原字符串,把小写的'h'替换成大写的'H',得到新的字符串。

    i = '3'
    a = '01234'
    if i in a:
        print(a*3)
        print(a+a)
        print(a[1:4])
        print(a[-1])
    print('4' in a)
    print('4' not in a)
    
    运行结果:
    012340123401234
    0123401234
    123
    4
    True
    False

    元组

    # 元组的赋值
    (month,day) = (11, 8)
    # 元组的嵌套
    ((1, 2), (2, 5))
    
    # 元组的比较
    >>> (4) > (5)
    False
    >>> (4) < (5)
    True
    >>> (1, 4) > (2, 4)
    False
    >>> (1, 4) > (1, 3)
    True
    >>> 
    
    # filter
    >>> a = (1, 3, 5, 7)
    >>> b = 4
    >>> filter(lambda x: x < b, a)
    <filter object at 0x7f25b3f71c10>
    # 列出 a 中小于 b 的元素
    >>> list(filter(lambda x: x < b, a)) 
    [1, 3]
    # 列出 a 中小于 b 的元素个数
    >>> len(list(filter(lambda x: x < b, a))) 
    2

    列表

    a_list = [123, 'abc']
    a_list.append('xyz')
    print(a_list)
    a_list.remove('abc')
    print(a_list)
    
    运行结果:
    [123, 'abc', 'xyz']
    [123, 'xyz']

    列表和元组都是有序的,可以存储任意数据类型的集合,主要区别:

    列表是动态的,长度可变,可以随意地增加、删减或者改变元素(mutable);存储空间略大于元组,性能略逊于元组。

    元组是静态的,长度固定,无法增加、删减或者改变(immutable);相对于列表更加轻量级,性能稍优。

    l = [1, 2, 'hello', 'world'] # 列表中同时含有int和string类型的元素
    tup = ('jason', 22) # 元组中同时含有int和string类型的元素
    
    l = [1, 2, 3, 4]
    l[3] = 40 # 索引从0开始,l[3]表示访问列表的第四个元素
    l
    [1, 2, 3, 40]
    
    tup = (1, 2, 3, 4)
    tup[3] = 40
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'tuple' object does not support item assignment
    
    
    # 要“改变”已有元组,只能重新开辟一块内存,创建新的元组
    tup = (1, 2, 3, 4)
    new_tup = tup + (5, ) # 创建新的元组new_tup,并依次填充原元组的值
    new _tup
    (1, 2, 3, 4, 5)
    
    l = [1, 2, 3, 4]
    l.append(5) # 添加元素5到原列表的末尾
    l
    [1, 2, 3, 4, 5]
    
    
    # Python 中的列表和元组都支持负数索引
    # -1 表示最后一个元素,-2 表示倒数第二个元素,以此类推
    l = [1, 2, 3, 4]
    l[-1]
    4
    
    tup = (1, 2, 3, 4)
    tup[-1]
    4
    
    
    # 列表和元组都支持切片操作
    l = [1, 2, 3, 4]
    l[1:3] # 返回列表中索引从1到2的子列表
    [2, 3]
    
    tup = (1, 2, 3, 4)
    tup[1:3] # 返回元组中索引从1到2的子元组
    (2, 3) 
    
    
    # 列表和元组都可以随意嵌套
    l = [[1, 2, 3], [4, 5]] # 列表的每一个元素也是一个列表
    tup = ((1, 2, 3), (4, 5, 6)) # 元组的每一个元素也是一个元组
    
    # 列表和元组可以相互转换 list((1, 2, 3)) [1, 2, 3] tuple([1, 2, 3]) (1, 2, 3)

    列表和元组常用的内置函数

    # count(item)表示统计列表/元组中 item 出现的次数
    # index(item)表示返回列表/元组中 item 第一次出现的索引
    l = [3, 2, 3, 7, 8, 1]
    l.count(3) 
    2
    l.index(7)
    3
    # list.reverse()和 list.sort()分别表示原地倒转列表和排序(注意,元组没有内置的这两个函数)
    l.reverse()
    l
    [1, 8, 7, 3, 2, 3]
    l.sort()
    l
    [1, 2, 3, 3, 7, 8]
    
    tup = (3, 2, 3, 7, 8, 1)
    tup.count(3)
    2
    tup.index(7)
    3
    
    # reversed()sorted()同样表示对列表/元组进行倒转和排序
    list(reversed(tup)) # reversed()返回一个倒转后的迭代器,list()函数再将其转换为列表
    [1, 8, 7, 3, 2, 3]
    sorted(tup) # sorted()返回排好序的新列表
    [1, 2, 3, 3, 7, 8]

    列表和元组存储方式的差异

    l = [1, 2, 3]
    l.__sizeof__()
    64
    tup = (1, 2, 3)
    tup.__sizeof__()
    48

    可以看到,对列表和元组,我们放置了相同的元素,但是元组的存储空间,却比列表要少 16 字节。这是为什么呢?

    由于列表是动态的,所以它需要存储指针,来指向对应的元素(上述例子中,对于 int 型,8 字节)。

    另外,由于列表可变,所以需要额外存储已经分配的长度大小(8 字节),这样才可以实时追踪列表空间的使用情况,当空间不足时,及时分配额外空间。

    l = []
    l.__sizeof__() # 空列表的存储空间为40字节
    40
    l.append(1)
    l.__sizeof__() 
    72 # 加入了元素1之后,列表为其分配了可以存储4个元素的空间 (72 - 40)/8 = 4
    l.append(2) 
    l.__sizeof__()
    72 # 由于之前分配了空间,所以加入元素2,列表空间不变
    l.append(3)
    l.__sizeof__() 
    72 # 同上
    l.append(4)
    l.__sizeof__() 
    72 # 同上
    l.append(5)
    l.__sizeof__() 
    104 # 加入元素5之后,列表的空间不足,所以又额外分配了可以存储4个元素的空间

    我们可以看到,为了减小每次增加 / 删减操作时空间分配的开销,Python 每次分配空间时都会额外多分配一些,这样的机制(over-allocating)保证了其操作的高效性:增加 / 删除的时间复杂度均为 O(1)。

    元组长度大小固定,元素不可变,所以存储空间固定。

    列表和元组的性能

    通过学习列表和元组存储方式的差异,我们可以得出结论:元组要比列表更加轻量级一些,所以总体上来说,元组的性能速度要略优于列表。

    另外,Python 会在后台,对静态数据做一些资源缓存(resource caching)。通常来说,因为垃圾回收机制的存在,如果一些变量不被使用了,Python 就会回收它们所占用的内存,返还给操作系统,以便其他变量或其他应用使用。

    但是对于一些静态变量,比如元组,如果它不被使用并且占用空间不大时,Python 会暂时缓存这部分内存。这样,下次我们再创建同样大小的元组时,Python 就可以不用再向操作系统发出请求,去寻找内存,而是可以直接分配之前缓存的内存空间,这样就能大大加快程序的运行速度。

    下面的例子,是计算初始化一个相同元素的列表和元组分别所需的时间。我们可以看到,元组的初始化速度,要比列表快 5 倍。

    python3 -m timeit 'x=(1,2,3,4,5,6)'
    20000000 loops, best of 5: 9.97 nsec per loop
    python3 -m timeit 'x=[1,2,3,4,5,6]'
    5000000 loops, best of 5: 50.1 nsec per loop

    但如果是索引操作的话,两者的速度差别非常小,几乎可以忽略不计。

    python3 -m timeit -s 'x=[1,2,3,4,5,6]' 'y=x[3]'
    10000000 loops, best of 5: 22.2 nsec per loop
    python3 -m timeit -s 'x=(1,2,3,4,5,6)' 'y=x[3]'
    10000000 loops, best of 5: 21.9 nsec per loop

    字典和集合

    字典是一系列由键(key)和值(value)配对组成的元素的集合。

    在 Python3.7+,字典被确定为有序(注意:在 3.6 中,字典有序是一个 implementation detail,在 3.7 才正式成为语言特性,因此 3.6 中无法 100% 确保其有序性),而 3.6 之前是无序的,其长度大小可变,元素可以任意地删减和改变。

    相比于列表和元组,字典的性能更优,特别是对于查找、添加和删除操作,字典都能在常数时间复杂度内完成。

    集合和字典基本相同,唯一的区别,就是集合没有键和值的配对,是一系列无序的、唯一的元素组合。

    字典和集合的内部结构都是一张哈希表。

    对于字典而言,这张表存储了哈希值(hash)、键和值这 3 个元素;

    而对集合来说,区别就是哈希表内没有键和值的配对,只有单一的元素了。

    # 字典和集合的创建
    d1 = {'name': 'jason', 'age': 20, 'gender': 'male'}
    d2 = dict({'name': 'jason', 'age': 20, 'gender': 'male'})
    d3 = dict([('name', 'jason'), ('age', 20), ('gender', 'male')])
    d4 = dict(name='jason', age=20, gender='male') 
    d1 == d2 == d3 ==d4
    True
    
    s1 = {1, 2, 3}
    s2 = set([1, 2, 3])
    s1 == s2
    True
    
    # 字典和集合可以是混合类型
    s = {1, 'hello', 5.0}
    
    
    # 字典访问可以直接索引键,如果不存在,就会抛出异常
    d = {'name': 'jason', 'age': 20}
    d['name']
    'jason'
    d['location']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    KeyError: 'location'
    
    # 可以使用 get(key, default) 函数来进行索引
    d = {'name': 'jason', 'age': 20}
    d.get('name')
    'jason'
    d.get('location', 'null')
    'null'
    
    # 集合并不支持索引操作,因为集合本质上是一个哈希表,和列表不一样。
    s = {1, 2, 3}
    s[0]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: 'set' object does not support indexing
    
    
    # 判断一个元素在不在字典或集合内
    s = {1, 2, 3}
    1 in s
    True
    10 in s
    False
    
    d = {'name': 'jason', 'age': 20}
    'name' in d
    True
    'location' in d
    False

    当然,除了创建和访问,字典和集合也同样支持增加、删除、更新等操作。

    d = {'name': 'jason', 'age': 20}
    d['gender'] = 'male' # 增加元素对'gender': 'male'
    d['dob'] = '1999-02-01' # 增加元素对'dob': '1999-02-01'
    d
    {'name': 'jason', 'age': 20, 'gender': 'male', 'dob': '1999-02-01'}
    d['dob'] = '1998-01-01' # 更新键'dob'对应的值 
    d.pop('dob') # 删除键为'dob'的元素对
    '1998-01-01'
    d
    {'name': 'jason', 'age': 20, 'gender': 'male'}
    
    s = {1, 2, 3}
    s.add(4) # 增加元素4到集合
    s
    {1, 2, 3, 4}
    s.remove(4) # 从集合中删除元素4
    s
    {1, 2, 3}

    不过要注意,集合的 pop() 操作是删除集合中最后一个元素,可是集合本身是无序的,你无法知道会删除哪个元素,因此这个操作得谨慎使用。

    对于字典,我们通常会根据键或值,进行升序或降序排序:

    d = {'b': 1, 'a': 2, 'c': 10}
    d_sorted_by_key = sorted(d.items(), key=lambda x: x[0]) # 根据字典键的升序排序
    d_sorted_by_value = sorted(d.items(), key=lambda x: x[1]) # 根据字典值的升序排序
    d_sorted_by_key
    [('a', 2), ('b', 1), ('c', 10)]
    d_sorted_by_value
    [('b', 1), ('a', 2), ('c', 10)]

    这里返回了一个列表。列表中的每个元素,是由原字典的键和值组成的元组。

    而对于集合,其排序和前面讲过的列表、元组很类似,直接调用 sorted(set) 即可,结果会返回一个排好序的列表。

    s = {3, 4, 2, 1}
    sorted(s) # 对集合的元素进行升序排序
    [1, 2, 3, 4]
    dict1 = {}
    print(type(dict1))
    dict1 = {'x':1, 'y':2}
    dict1['z'] = 3
    print(dict1)
    for key in dict1.keys():
        print('%s: %d' %(key, dict1[key]))
    
    运行结果:
    <class 'dict'>
    {'x': 1, 'y': 2, 'z': 3}
    x: 1
    y: 2
    z: 3
    
    # 列表推导式
    # 从 1 到 10 所有偶数的平方
    alist = [i*i for i in range(1,11) if(i%2 == 0)]
    print(alist)
    
    # 字典推导式
    # 初始化为 0
    a = ('month', 'day')
    dict2 = {i:0 for i in a}
    print(dict2)
    
    运行结果:
    [4, 16, 36, 64, 100]
    {'month': 0, 'day': 0}

    条件与循环

    # 条件语句
    if condition_1:
        statement_1
    elif condition_2:
        statement_2
    ...
    elif condition_i:
        statement_i
    else:
        statement_n
        
    
    # 循环语句
    for item in <iterable>:
        ...
        
    while condition:
        ....
    #条件语句
    s = input("Please enter s:") # s is a string
    if s == '123':
        print('s = 123')
    else:
        print('s != 123')
    
    
    #循环语句
    #i = 4 5
    for i in range(4,6):
        j = i*2
        print('i=%d, j=%d' %(i,j))
        
    while True:
        print('True')
        break
    
    运行结果:
    Please enter s:12
    s != 123
    i=4, j=8
    i=5, j=10
    True

    文件操作

    open() 打开文件

    read() 输入

    readline() 输入一行

    seek() 文件内移动

    write() 输出

    close() 关闭文件

    # open mode: r read, w write, a append
    file1 = open('name.txt','a') 
    file1.write('cindy
    jack
    pony')
    file1.close()
    
    file2 = open('name.txt')  # default mode: r
    print(file2.tell())
    print(file2.read())
    print(file2.tell())
    
    # seek(offset, whence) whence: 0 file start, 1 file current, 2 file tail
    file2.seek(11, 0)
    print('seek: %d' %file2.tell())
    print('read: %s' %file2.read())
    
    file2.seek(0, 0)
    print('seek: %d' %file2.tell())
    #print('readline: %s' %file2.readline())
    
    for line in file2.readlines():
        print(line)
        print('===')
        
    file2.close()
    
    运行结果:
    0
    cindy
    jack
    pony
    15
    seek: 11
    read: pony
    seek: 0
    cindy
    
    ===
    jack
    
    ===
    pony
    ===

    输入与输出

    input() 函数暂停程序运行,同时等待键盘输入;直到回车被按下,函数的参数即为提示语,输入的类型永远是字符串型(str)。

    print() 函数则接受字符串、数字、字典、列表甚至一些自定义类的输出。

    异常

    异常是在出现错误时采用正常控制流以外的动作。

    异常处理的一般流程是: 检测到错误,引发异常;对异常进行捕获的操作

    try:
        <监控异常>
    except Exception[, reason]:
        <异常处理代码>
    finally:
        <无论异常是否发生都执行>

    try:
        year = int(input('input year:'))
    except ValueError:
        print('year should be a integer.')
    
    try:
        print(1/'a')
    except Exception as e:
        print(' %s' %e)
    
    try:
        raise NameError('helloError')
    except NameError:
        print('my custom error')
    
    try:
        a = open('name.txt')
    except Exception as e:
        print(e)
    finally:
        a.close()

    模块

    模块是在代码量变得相当大之后,为了将需要重复使用的有组织的代码段放在一起,这部分代码可以附加到现有的程序中,附加的过程叫做导入(import)。

    导入模块的一般写法:
    import 模块名称
    from 模块名称 import 方法名

    知识图谱

  • 相关阅读:
    SpringBoot Data Jpa基本使用
    spring cloud oauth2(五) 白名单设置
    spring cloud oauth2(四) 资源服务搭建
    spring cloud oauth2(三) 自定义授权类型 手机号+短信验证码
    spring cloud oauth2(二) 自定义授权类型 图片验证码
    spring cloud oauth2(一) 授权服务搭建
    设计模式 选自《闻缺陷则喜》此书可免费下载
    设计模式六大原则 节选自《闻缺陷则喜》(此书可免费下载)
    架构模式 节选自《闻缺陷则喜》(此书可免费下载)
    架构内容 节选自《闻缺陷则喜》(此书可免费下载)
  • 原文地址:https://www.cnblogs.com/sunnycindy/p/15499972.html
Copyright © 2011-2022 走看看