Python3.8总结

文章目录

  • 小知识点
  • 模块和包
    • 1.模块信息
    • 2.用python解释器执行模块
    • 3. 包
    • 4. 导入模块
  • 函数
    • 1. 基本语法
    • 2. 参数默认值
    • 3. 不定参数
    • 4. 关键字/位置参数
    • 5. 解包参数列表
    • 6. lambda表达式
    • 7. 函数标注
  • 数据结构
    • 1.List
    • 2.Tuple
    • 3.Set
    • 4.Dict
    • 5.List和Tuple切片
    • 6.推导式
    • 7.遍历
    • 8.排序
  • IO
    • 1.格式化字符串
    • 2.读写文件
    • 3.Json
  • 错误和异常
    • 1.处理过程
    • 2.自定义异常
  • 面向对象
  • 网络访问
    • 1.urllib使用
    • 2.pycharm中response没有提示?
  • 并发
    • 1.线程
  • 日志
  • 常用标准库
    • 1.collections
  • 其他
    • 1.修改pip镜像

小知识点

  1. 注释
# 这是注释
  1. 字符串字面量
  • 使用单引号'content',双引号"content"都可以
  • 多行使用3个单引号或3个双引号都可以
  • 字符串可以使用*重复,+拼接'a'*3+'b'
  • 相邻的多个字符串字面量自动连接到一起'py' 'thon'
  1. 变量赋值
  • 允许在一个表达式对多个变量赋值
    a, b = 1, 'a'
  • 序列解包
l = [1, "a"]或l=(1, "a")
a, b = l

模块和包

一个python文件就是一个模块

1.模块信息

  • 获取模块中定义的变量,模块,函数等,不会列出内置函数的变量的名称
# 获取当前模块的
dir()
# 获取指定模块的
import m
dir(m)
  • 获取模块本身的信息
# 模块名
__name__
# 模块文件的绝对路径
__file__
# 模块所在的包
__package__

2.用python解释器执行模块

# 命令
python m.py <args>
# 注意:这样执行时m.py的__name__为__main__
# 如果只是导入的话
import m
print(m.__name__) # 为m

# 因此如果要在测试模块内容,可以在模块内添加
if __name__ == "__main__":
	#code
# 这样在别的模块import时,不会执行这些测试代码

3. 包

包是一个目录,该目录必须有一个__init__.py文件

4. 导入模块

  • import时在哪里找到模块?
    sys.path
  • 在import时发生了什么?
    import时,目标模块整体导入进来,并以模块名存在,目标模块如果有可执行代码,将会执行。
    注意: 出于效率的考虑,每个模块在每个解释器会话中只被导入一次。因此,如果你更改了你的模块,则必须重新启动解释器, 或者,如果它只是一个要交互式地测试的模块,使用importlib.reload(modulename)
  • 有哪些导入方法
# 导入模块
import mod
mod.func()
# 从包中导入模块
import pkg.mod
pkg.mod.func()
# 更方便的方法
from pkg import mod
mod.func()
# 导入指定函数
from mod import func
func()
# 从包中导入*
# 需要在包的__init__.py文件中指定
__all__ = ["Mod1"]
# 这样
from pkg import *
# 会导入Mod1模块
# 可以使用相对引用
from .. import Mod1

函数

https://docs.python.org/zh-cn/3.8/tutorial/controlflow.html

1. 基本语法

def f1():
    """
    基本函数定义
    :return: 返回Hello
    """
    return "hello"

2. 参数默认值

def f2(a, b=1):
    """
    带默认值的函数
    :param a: 参数a
    :param b: 参数b的默认值为1
    :return: 返回a+b
    """
    return a+b
  • 注意:不要将参数默认值设置为可变对象(列表,字典等)
    Python3.8总结_第1张图片

3. 不定参数

def f3(*args, **kvs):
    """
    不定参数
    :param args:不定参数,即tuple
    :param kvs:不定键值对,即dict
    """
    print("f3:")
    print("args:", args)
    print("kvs:", kvs)


f3("arg1", "arg2", k1="v1", k2="v2")

4. 关键字/位置参数

/前面强制为位置参数,调用时不能添加关键字,在*后面的强制为关键字参数,调用时必须添加关键字,其他的不进行限制

def f4(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
    """
    关键字或位置参数
    """
    pass


f4(1,2,3,kwd1=4,kwd2=5)

5. 解包参数列表

def f5(*args, a, b):
    """
    解包参数列表
    """
    print("f5:")
    print(args)
    print(a)
    print(b)


tp = (1, 2, 3)
dt = {
     "a": 1, "b": 2}
f5(*tp, **dt)

6. lambda表达式

def f6(n):
    """
    返回lambda表达式构成的匿名函数
    """
    return lambda x: x + n
    # 上面语句相当于下面的
    # def ff(x):
    #     return n+x
    # return ff


print("f6:", f6(42)(5))

7. 函数标注

指定具体类型,调用时类型不对时将会获得警告,但不会出错

def f7(a: int, b: str) -> list:
    """
    函数标注
    :rtype: list值
    :param a: int值
    :param b: str值
    :return: 返回list
    """
    return [a, b]


print("f7:", f7(2, 'a'))

数据结构

1.List

  • 初始化
# 空的
l = []
l = list()
# 有初始数据
l = [1,"a"]
l = list([1,"a"])
  • 取值
l[0]
  • 添加或修改
l.append(2)
l[0] = 2
l.insert(0,2)
  • 删除
del l[0]
#移除列表中某个值的第一个匹配
l.remove('a')
#弹出,默认index=-1(最后一个元素)
l.pop(index) 
  • 其他函数
#列表元素个数
len(l)
#列表元素最大值 
max(l)
#列表元素最小值 
min(l)
#统计某个元素在列表中出现的次数 
l.count('a')
#在列表末尾一次性追加多个值 
l.extend([1,2,3])
#某个元素在列表中的第一个索引 
l.index('a')
#列表反向 
l.reverse()
#清空 
l.clear()
#复制 
l.copy()

2.Tuple

与List类似,但其中的元素不可变不可修改不可删除

  • 初始化
# 括号可以加上或省略
t = 1,
t = (1,)
t = 1,'a'
t = (1,'a')
  • 访问
t[0]
  • 不能增加元素,但可以对元组进行连接组合
t = (1,) + ('a',)
  • 如果元组中包含可变对象,对象的属性是可变的
t = (1,[])
t[1]可变

3.Set

  • 初始化
# 空的
s = set()
# 有初始值
s = {
     1,'a'}
s = set((1,'a'))
  • 添加元素
# 基本数据类型
s.add(1)
s.add('a')
# 集合类型
s.update([2,3])
  • 删除元素
# 存在则删除,不存在则报错
s.remove('a')
# 存在则删除,不存在不报错
s.discard('a')
# 随机删除一个元素
s.pop()
  • 运算符
# 差集 
s1 - s2
# 并集
s1 | s2
# 交集
s1 & s2
# 两个集合不重复的,即交集-并集
s1 ^ s2
  • 其他函数
使用 解释
s.clear() 清空
s1.difference(s2) s1-s2
s1.difference_update(s2) s1 = s1-s2
s1.intersection(s2) s1&s2
s1.intersection_update(s2) s1 = s1&s2
s1.isdisjoint(s2) 是否包含相同的元素
s1.issubset(s2) s1是否为s2的子集
s1.issuperset(s2) s1是否为s2的父集
s1.union(s2) s1
s1.symmetric_difference(s2) s1和s2不重复的元素
s1.symmetric_difference_update(s2) s1=s1和s2不重复的元素

4.Dict

  • 初始化
#空的
d = {
     }
d = dict()
# 有初始值
d = {
     1:'a',2:'a'}
# 从序列初始化
d = dict.fromkeys([1,2],'a')
  • 访问
# 按key,不存在则报错
d['a']
# 使用get
d.get('a',default=None)
  • 添加或更新
# 直接添加或更新
d[1] = 'c'
# 如果存在key则不变,否则添加
d.setdefault(1,'a')
# 批量添加或更新
d1.update(d2)
  • 删除
# 直接删除,不存在此key则报错
del d['a']
# 删除,并返回值,不存在此key则报错
d.pop('a')
# 随机删除,并返回键值对
d.popitem()
  • 其他函数
函数 解释
d.clear() 清空
d.copy() 复制
d.values() 值序列(类型为dict_values),可以解包生成List,Set或Tuple
d.keys() 键序列,同上
d.items() 键值对序列,同上
‘a’ in d或d.has_key(‘a’) key是否在dic中(不要使用’a’ in d.keys())

5.List和Tuple切片

l = ['a','b','c','d','e','f','g','h','i']
#第一个元素索引是0,倒数第一个元素索引是-1.
#取前5个元素
l[:5]
#取第3个到第五个元素
l[2,5]
#前5个,每2个取一个
l[:5:2]
#取后5个
l[-5:]
#后5个,每2个取1个
l[-5::2]

6.推导式

  • 基本结构
new = [exp(i) for i in old if filter_exp(i)]
exp(i) 关于i的表达式
filter_exp(i) 过滤某些值
# 1到30的偶数组成的list
l = [x for x in range(1, 31) if x % 2 == 0]
# 1到30的奇数组成的Set
s = {
     x for x in range(1, 31) if x % 2 == 1}
# 键值对互换
d1 = {
     'a': 10, 'b': 34}
d2 = {
     v: k for k, v in d1.items()}

7.遍历

  • 遍历List/Tuple
for v in l
for i in range(len(l))
for i,v in enumerate(l)
  • 遍历Set
for v in s
for i,v in enumerate(s)
  • 遍历Dict
for k in d
for kv in d.items()
for k,v in d.items()
  • 更多技巧
# 同时遍历多个序列,元素需要一一匹配时,使用zip函数
questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
	print('What is your {0}?  It is {1}.'.format(q, a))

#逆向循环一个序列,使用reversed函数
for v in reversed([1,2,3]):

#遍历一个排序后的序列
for v in sorted(...)

#循环时修改内容,可以创建一个新的序列,这样简单和安全

8.排序

排序指南

  • 使用sortsorted
#sort直接在原序列排序
#sorted可以排序任意可迭代对象,生成新的序列
l.sort(key,reverse)
l2 = sorted(iter,key,reverse)
  • 参数key解释
    key的类型为Optional[Callable[[_T], Any]],即一个函数,参数为l的元素,返回Any
# key需要一个函数,这里使用lambda匿名函数
l = ['a', 'aaa', 'aa']
l.sort(key=lambda x: len(x), reverse=True)

# 也可以直接指定函数
l.sort(key=str.lower)
l.sort(key=methodcaller('lower'))

# 如果每个元素都是元组,按照元组的第二个元素排
l.sort(key=lambda t:t[1])
l.sort(key=itemgetter(1))

# 如果每个元素都是对象,按照对象的属性排
students.sort(key=lambda student:student.age)
students.sort(key=attrgetter("age"))

#多关键字排序:
sorted(student_objects, key=attrgetter('grade', 'age'))
sorted(list, key=itemgetter(0,1))

#复杂排序:如先升序后降序,排序两次
s = sorted(student_objects, key=attrgetter('age'))     
sorted(s, key=attrgetter('grade'), reverse=True) 

IO

输入输出
字符串参考指南

1.格式化字符串

  • f字符串
# 在字符串字面量中使用表达式
a=1
b='hello'
print(f"{a},{b}")

# 表达式中可以对变量格式化处理
f"{math.pi:.3f}" #保留3位小数

# 最小字符宽度
f"{name:10}" #最小宽度为10

# 对变量调用函数格式化
f"{name!s}"
# !s 为str()
# !r 为repr()
# !a 为ascii()
  • 使用函数
    str.format()
>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred',other='Georg'))
The story of Bill, Manfred, and Georg.
>>> table = {
     'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

str()

# 将变量用字符串表示
a = 'hello'
str(a) # 字符串hello

repr()

# 将变量用字符串表示,并加上引号
a = 'hello'
repr(a) # 字符串`hello`

2.读写文件

def read_file():
    with open("testFile") as f:
        for line in f:
            f.readlines()
            print(line)


def write_file():
    with open("testFile", 'a') as f:
        f.write("str\r\n")
  • 打开文件的模式
'r'      只读
'w'     覆盖写
 'x'     创建写
'a'      追加
  • 读文件应该使用哪种函数?
# 1.f.read(n) 一次性读取n个字符
# 2.f.readline(limit) 一次性读一行的limit个字符
# 3.f.readlines() 一次性读全部的行存为list到内存
  • for line in ffor line in f.readlines()
# for line in f 这是python推荐的,内存高效的,快速的,可以读大文件,python会自动管理内存
# for line in f.readlines() 不能读大文件,readlines会读全部内容到内存

3.Json

todo:等了解第三方库后再更新这里

错误和异常

1.处理过程

def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError as err:
        print(f"ZeroDivisionError:{err}")
    except ValueError:
    	print("value err")
    except Exception :
    	print("other err")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")

2.自定义异常

class InputError(Exception):

    def __init__(self, expression, message):
        self.expression = expression
        self.message = message
# 抛出异常
raise InputError

面向对象

# 面向对象

import abc
from enum import Enum, unique


@unique  # unique确保无重复值
class Weekday(Enum):
    """
    枚举类
    """
    # 左边为name,右边为value
    Sun = 0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6


class Person(metaclass=abc.ABCMeta):
    """
    Person 为抽象类,Person的子类需要实现抽象方法
    """

    @abc.abstractmethod
    def abs_m(self):
        print("Person:abs_m")


class Student(Person):
    """
    Student Doc
    """

    # 实现抽象方法
    def abs_m(self):
        print("absMethod")

    # 使用父类引用
    def sup(self):
        super().abs_m()

    # count为类属性
    count = 0

    # 类方法
    @classmethod
    def cm(cls):
        print("classMethod:", Student.count)

    # 静态方法
    @staticmethod
    def sm():
        print("staticMethod:", Student.count)

    # 实例私有方法
    def __p(self):
        # 如果没有使用到self,这里可能会警告this method may be static
        print("私有方法", self)

    # 定义该类只允许有这些属性
    __slots__ = ('name', '__age', "_gender")

    def __init__(self, name, age, gender):
        # 这是实例属性,外部可以直接访问
        self.name = name
        # 两个下划线开头是私有属性,在外部不能访问(如果要强行访问,可以使用s._Student__name,但不建议这样做)
        self.__age = age
        # 一个下划线开头也表示私有属性,在外部可以直接访问,但不建议访问(为什么这样设计?)
        self._gender = gender
        pass

    # 双下划线开头和结尾的是特殊方法或变量,不是私有的,外部可以访问
    # 因此不要把方法或属性名定义为双下划线开头和结尾
    def __str__(self):
        return f"{self.name}, {self.__age}, {self._gender}"


if __name__ == '__main__':
    s = Student("jack", 12, "male")

    # s的具体类型
    print(type(s).__name__)

    # 内置attr函数使用
    print(hasattr(s, "name"))
    print(getattr(s, "name"))
    # print(delattr(s, "name"))
    # print(setattr(s, "abc", 1))

    # s是否是某个类型
    print(isinstance(s, Student))

    # Student类是否是某个类的子类
    print(issubclass(Student, object))

    # 调用s.__str__()方法
    print(s)

    # 使用枚举类
    day = Weekday.Mon
    print(day.name)
    print(day.value)

网络访问

1.urllib使用

from urllib import request
import http.client

if __name__ == '__main__':
    with request.urlopen('http://www.baidu.com') as resp:  # type:http.client.HTTPResponse
        print(resp.readlines())
        

2.pycharm中response没有提示?

https://www.jetbrains.com/help/pycharm/2017.1/type-hinting-in-pycharm.html

# 3种方法
# 1
resp = request.urlopen('http://www.baidu.com') # type:http.client.HTTPResponse

# 2
resp = request.urlopen('http://www.baidu.com') 
assert isinstance(resp, http.client.HTTPResponse)

# 3
resp = request.urlopen('http://www.baidu.com')
"""
:type:http.client.HTTPResponse
"""

并发

1.线程

# 两种方式创建线程
# 第一种,使用继承
class MyThread(Thread):

    def run(self):
        print("使用继承")


if __name__ == '__main__':
    my = MyThread()
    my.start()
# 第二种 
    t = Thread(target=lambda: print("直接使用Thread类"))
    t.start()

日志

常用标准库

https://docs.python.org/zh-cn/3.8/library/index.html
https://www.liaoxuefeng.com/wiki/1016959663602400/1017681679479008

1.collections

  • namedtuple
    很方便地定义一种数据类型,它具备tuple的不变性,又可以根据属性来引用,使用十分方便
from collections import namedtuple

if __name__ == '__main__':
    Point = namedtuple("Point", ["x", "y"])
    p = Point(10,20)
    print(p.x)
    print(p.y)
    print(p)
  • deque
    双向链表可以快速插入,删除元素
  • defaultdict
    使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict
    # 带默认值的dict
    dd = defaultdict(lambda: "None")
    print(dd["k"])
  • OrderedDict
    有序Dict按插入顺序排序
  • ChainMap
    将多个Dict组成一个Dict,查找key时按照顺序依次查找
  • Counter
    计数器:为序列元素计数
    c = Counter()
    c.update((1, 1, 1, 2, 2))
    print(c)

其他

1.修改pip镜像

  • 创建文件~/.pip/pip.conf
  • 文件内容
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
[install]
trusted-host=pypi.tuna.tsinghua.edu.cn

你可能感兴趣的:(python)