python基础:廖雪峰的官方网站Python(部分)笔记

1. 数据类型和变量

  • 对于很大的数,python允许再数字中间以_分隔,比如1000000000和1_000_000_000是等价的
  • 如果字符串内部有很多字符都要转义,可以使用r""或r’'取消字符串内部的转义
  • 如果字符串内部有很多换行,可以使用多行字符串```,比如

  • python中可以对同一变量反复赋值,而且可以是不同类型的数据

2. 编码和输出

2.1 编码

  • ASCII编码1个字节,Unicode编码通常是2个字节(部分4字节),ASCII转Unicode直接前面补0

  • UTF-8编码是针对Unicode的一种可变长度字符编码,UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。

  • 在计算机内存中,统一使用Unicode编码,字符串是str类型,以字符为单位。当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码,是以字节为单位的bytes类型,bytes类型用b’'或b""表示

  • str类型通过encode()方法转换为指定编码(eg,ascii,utf-8)的bytes类型,bytes类型通过decode()方法转换为指定编码的str类型

  • 由于Python源代码也是一个文本文件,需要将该源码保存为UTF-8编码,比如源码开头有:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    

    第一行注释是为了告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;

    第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。

2.2 格式化输出

  • %用来格式化字符串,比如

    print('I am %s, I am %d years old, I am %.2f cm in height.' % ('Zhang', 22, 180.5))
    
    # %s可以将任意类型转换为字符串输出
    print("I am %s, I am %s years old" % ('Zhang', 22))
    
  • 使用字符串的format()方法格式化输出

    print('I am {0}, I am {1:.2f}cm in height'.format('Zhang', 180.512))
    
  • 使用f-string(f开头的字符串),会进行相应的变量替换

    a, b = 1, 2.125
    print(f'a is {a}, b is {b:.2f}')
    

3. 函数

3.1 函数

  • 函数名其实就是一个指向函数对象的引用,可以把函数名赋给一个变量,相当于取了别名

    a = abs
    print(a(-1))
    
  • 函数的返回值其实是一个tuple,按位置取出

3.2 函数参数

  • 必选参数(也称位置参数)在前,默认参数在后

    • 如果在参数列表中加入斜杠/,则/前面的变量只能通过位置参数方式传参,而且不能有默认值
  • 默认参数必须是不可变对象(比如None,数字,字符串,bool)

    python可变类型和不可变类型的区别 python的可变和不可变数据类型

    • 默认参数的值在函数定义的时候已经确定

    • 默认参数如果没有赋值,那么默认参数重新指向默认值

      • 如果默认参数是不可变类型,函数中间改变参数的值时,相当于新建了一个对象,内存地址发生了改变
      • 但如果默认参数是可变类型,函数中间改变参数的值时,不会新建对象,内存地址不改变。因此下次使用该函数时默认参数的值会不再是初始值,eg:
      def func(lst = []):	# 错误写法,应该携程lst = None,后面在函数内部进行if判断,然后初始化
      	lst.append("end")
      	print(lst)
      func()	# ['end']
      func()	# ['end', 'end']
      func()	# ['end', 'end', 'end']
      
    • 还要注意Python函数的参数传递是共享传参,即将实参的引用传递给函数对应的形参,因此对于不可变类型的数据经过传参在函数内部改变后,函数外的实参也会改变

  • 可变参数:用于接受多个(或0个)参数,且参数个数不确定,eg:

    def add(*numbers):	# 在函数内部,numbers是一个tuple,所以无法修改
    	# add numbers
    # 用法1:
    add(1,2,3)
    
    # 用法2:
    lst = [1, 2, 3]
    add(*lst)
    
    • 同时可变参数可以收集未匹配的位置参数,元组解包的过程中会将每一个元素依次放入到位置参数
    • *出现在函数定义时,表示可变参数,*出现在函数调用时,表示解包功能
  • 关键字参数:接受多个(或0个)含参数名的参数,eg:

    def person(name, age, **kw): # 函数内部对kw(dict类型)的改动不会影响到函数外的实参,因为传入的是拷贝
    	print('name', name, 'age', age, 'other', kw)
    extra = {'city': 'Beijing'}
    person('zhang', 22, **extra)
    
  • 命名关键字参数:用于限制关键字参数的名字,*后面的参数被视为命名关键字参数

    • 如果有可变参数,后面就不需要*

    • 命名关键字参数可以有默认值

       def person(name, *, age=22, city):
       	pass
       person("zhang", city="beijing")
      
  • 参数组合:必选参数–>默认参数–>可变参数–>命名关键字参数–>关键字参数

4. 数据结构及算法

4.1 数据结构

  • tuple:当tuple中只有一个元素时,需要在该元素加一个逗号防止歧义(输出也有这个逗号),eg: tup = (1,)
  • 切片:可以对list,tuple, string切片操作

4.2 列表生成式

[表达式 for循环 过滤条件]

lst = [x if x % 5 == 0 else -x for x in range(1, 31) if x % 2 != 0 ]
# for x in range(1, 31)是for循环部分,if x % 2 != 0是过滤条件(不能有else语句)
# x if x % 5 == 0 else -x是表达式部分,必须有else语句(如果有if语句)

4.3 生成器

列表元素可以通过某种算法推算出来,节省内存

  • 使用方法1:类似列表生成式

    gen = (x*x for x in range(10))
    # 使用next(gen)获得generator的下一个返回值,generator对象是可迭代对象
    for x in gen:
    	print(x)
    
  • 使用方法2:yield关键字

    def Fibonacci(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b	# pring(b)
            a, b, n = b, a+b, n+1
    for x in Fibonacci(6):
        print(x)
    

    generator函数在每次调用next()的时候执行,遇到yield关键字就返回,下次执行时从上次返回的yield关键字处继续执行,generator对象可迭代

  • 技巧:用生成器返回一个无限序列,比如返回奇数序列:

    def odd_iter():
    	n = 1
    	while True:
    		n += 2
    		yield n
    

4.4 迭代器

  • 可迭代对象Iterable:容器类(list,tuple,dict,set,str)和generator,凡是可迭代对象都可以迭代,enumerate函数将list转换成index-element pair

  • 迭代器Iterator:generator是Iterator(计算是惰性的),使用iter()Iterable转换为Iterator

    from collections.abs import Iterable, Iterator
    isinstance("abc", Iterable)
    

5. 函数式编程

5.1 高阶函数

​ 函数(名)作为参数传入另一个函数

  • map(f, Iterable) -> Iterator:将函数f作用在Iterable中每个元素(将运算规则抽象了,增加了可读性)

  • reduce(f, Iterable):reduce把结果继续和下一个元素进行累积运算,返回值是f的返回值类型需要先导入

    # 具体过程:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
    from functools import reduce
    
  • filter(f, Iterable) -> Iterator:将函数f作用在Iterable中每个元素,如果返回值是True就保留,否则丢弃

  • sorted(Iterable, key=func, reversed=False)

5.2 匿名函数

lambda 参数: 表达式,可以将匿名函数赋给一个变量

5.3 闭包

  • 外部函数返回内部函数时,外部函数的变量和参数仍然被返回的内部函数所引用

    def lazy_sum(*args):
    	local_var = 0
    	def sum():
    		# calc result, use local_var and *args
    		return result
    	return sum
    
  • 返回的函数并非立刻执行,如果返回的函数中使用了相同的局部变量,最后函数执行是绑定到了相同的参数,这部分不是很懂

  • 如果内部函数修改外部函数的变量,直接修改是不行的(因为虽然内部函数可以使用外部函数的变量,但是没有初始化),需要使用nonloacl关键字表示该变量在外部函数中已经初始化了

    def lazy_sum(*args):
    	local_var = 0
    	def sum():
    		nonlocal local_var	# 表示这个变量是外部函数的变量,且已经初始化为0
    		tmp = 0	# 这是内部函数的局部变量,每次调用sum时重新初始化
    		# calc
    		return result
    	return sum
    

5.4 装饰器Decorator

在代码运行期间动态增加功能的方法,本质上是一个返回函数的高阶函数

  • 写法一:不带参数

    def log(func):
    	@functools.wraps(func) # 在运行add函数创建函数对象时,eg:a=add,a的__name__属性不加这句变成了wrapper,对于某些依赖函数签名的代码会出错,加了之后a的__name__属性变成了add
    	def wrapper(*args, **kw):
    		print(func.__name__)
    		return func(*args, **kw)
    	return wrapper
    
    @log
    def add(x, y):
    	return x+y
    
    add(1,2)
    # 如果不加@修饰器使用高阶函数的写法:log(add)(1,2)
    
  • 写法二:带参数

    def log(text):
    	def decorator(func):
    		@functools.wraps(func)
    		def wrapper(*args, **kw):
    			print(text, func.__name__)
    			func(*args, **kw)
    			print('end')
    		return wrapper
    	return decorator
    
    @log("test") # 注意装饰器的参数不能是形参,一定要赋值
    def add(x, y):
    	return x+y
    
    add(1,2)
    # 如果不加@修饰器使用高阶函数的写法:log("test")(add)(1,2)
    

5.5 偏函数

将函数的一个参数固定(即设置默认值),返回一个新的函数,使之调用更简单

par_func = functools.partial(func, *args, **kw)

6. 面向对象编程

6.1 基础

6.1.1 类Class

​ 相当于一种数据类型

6.1.2 访问限制

​ 双下划线变量是private变量,不要在类外直接修改

class Student(object):
    def __init__(self, name):
        self.__name = name
    def get_name(self):
        print(self.__name)
    def set_name(self, name):
        self.__name = name

stu = Student("zhang")
stu.get_name()
print()
stu.__name = "li"	# Python解释器将Student类中的__name变量修改成了_Student__name,此处的__name变量是一个新的变量了
stu.get_name()
print(stu.__name, stu._Student__name)
print()
stu.set_name("zhao")
stu.get_name()
print(stu.__name, stu._Student__name)

6.1.3 获取对象信息

  • isinstance()判断一个对象是否是某个类型,或者位于该类型的父类继承链上。并且可以判断一个变量是否是某些类型中的一类,eg:

    isinstance([1,2,3], (list, tuple))
    
  • dir()获取一个对象的所有方法和属性

  • hasattr(obj, 'x'):判断obj对象是否有属性x

  • getattr(obj, 'x', 404):获取obj对象的属性x,如果没有返回404

  • setattr(obj, 'x', 1):设置obj兑现的属性x

6.1.4 属性

​ 相同名称的实例属性将屏蔽类属性

  • 实例属性:

    class Student:
    	def __init__(self):
    		self.name = 'zhang'
    stu = Student()
    print(stu.name)	# 使用实例名.实例属性来访问实例属性
    
  • 类属性:

    class Student:
    	name = 'zhang'
    print(Student.name)	# 使用类名.类属性来访问类属性
    

6.1.5 多态

​ 子类重写父类的方法

  • 比如函数func的参数是Animals类型,继承自Animals类型的Dog、Cat类型(对拓展开放)的实例同样可以传入func函数(对修改封闭)
  • 静态语言(eg:Java)如果函数参数是Animals类型,就必须传入Animals类型或是Animals类型的子类;但是动态语言(eg:Python)如果函数参数是Animals类型,只需要保证传入的对象中有函数中调用的方法即可(不需要必须是Animals类型,即鸭子类型)

6.2 @property

​ 将getter/setter方法简化为对属性的赋值和访问

  • 对实例属性使用getter和setter:

    class Student:
        def get_score(self):
            return self._score
        def set_score(self, score):
            ''' type check '''
            self._score = score
    
    stu = Student()
    stu.set_score(60)
    print(stu.get_score())
    
  • 使用@property

    class Student:
        @property	# 表明将score(原来的getter方法)当作类的属性
        def score(self):
            return self._score	# getter、setter操作的变量
    
        @score.setter	# @property创建了另一个装饰器@property.setter,可以将setter方法变成属性赋值,如果只设置@property而不设置@property.setter,则该属性被认为是只读属性
        def score(self, score):
            ''' type check '''
            self._score = score
    
    stu = Student()
    stu.score = 60	# 原来的setter方法
    print(stu.score)	# 原来的getter方法
    

6.3 多重继承

  • MixIn设计模式:以一个父类为主类,其他父类视为增加的功能

6.4 定制类

  • __str__:重新定义print类实例的输出

    class Student:
    	def __str__(self):
    		return 'Student object'
    print(Student())
    
  • __iter__:返回一个用于for循环的迭代对象,该迭代对象调用 __next__方法获取下一个值

    class Fibonacci(object):
    	def __init__(self):
    		self.a, self.b = 0, 1
    	def __iter__(self): 
    		return self	# 实例本身就是迭代对象,故返回自己
    	def __next__(self):
    		self.a, self.b = self.b, self.a+self.b
    		return self.a
    for n in Fibonacci():
    	if n > 100:
    		break
    	print(n)
    
  • __getitem__:按下标(或者key)取值,同样还有__setitem____delitem__

    class Fibonacci(object):
    	def __getitem__(self, n):	# 如果想实现切片操作,需要进一步完善
    		a, b, = 1, 1
    		for x in range(n):
    			a, b = b, a+b
    		return a
    
  • __call__:对类的实例进行调用

    class Student(object):
    	def __call__(self, txt):
    		print("test: %s" % txt)
    s = Student()
    s("txt")	# 对实例进行调用
    callable(s)	# 判断一个对象能否被调用
    
  • __slots__:Python可以给实例或类绑定方法或属性,使用__slots__可以限制绑定的实例的属性和方法

6.5 枚举类

将一组常量定义在一个类中,且该类不可变

from enum import Enum 
Mon = Enum('Month', ("Jan", "Feb", "Mar"))	# Month类型的枚举类
for name, member in Mon.__members__.items():
	print(name, '=>', member, ',', member.value)
print(Mon(1))		# 根据value的值获取枚举常量
print(Mon.Jan)		# 根据成员名称引用枚举常量
print(Mon['Jan'])
print(Mon.Jan.value)	# 获取计数,从1开始

7. 调试

  • 断言:可以使用python -O test.py关闭assert

    def func(x):
    	assert x!=0, "x is zero"
    	return x//10
    
  • 日志logging:将print替换为logging

8. 文件

8.1 文件读写

with open('tset.txt', 'r', encoding='utf-8') as f:
	# f.read() # 会将文件内容一次性读取
	for line in f.readlines():
		print(line.strip())	# 把末尾的'\n'删掉
		# 或者line=f.readline()循环读直到line==''
# 当文件写入磁盘时,操作系统不会将数据立刻写入磁盘,而是放到缓存中,f.close()才保证全部写入磁盘

8.2 JSON文件读写

  • json.dump(obj, f):python对象obj序列化到文件f
  • json.dumps(obj):将python对象obj序列化为json格式字符串
  • json.load(f):将文件f反序列化为python对象
  • json.loads():将json格式字符串反序列化为python对象

8.3 StringIO与BytesIO

  • StringIO:在内存中读写str,BytesIO:在内存中读写bytes,与读写文件有相同的接口

8.4 操作文件和目录

  • os.uname()获取详细的系统信息
  • os.environ查看系统变量
  • os.path.abspath('.')当前目录的绝对路径
  • os.path.join()将多个路径合成一个
  • os.path.split()将路径拆分为两个部分,后一部分为最后的目录或文件名
  • os.path.splitext()得到路径的文件拓展名
  • os.mkdir(), os.rmdir(), os.remove(), os.rename()
  • shutil.copyfile()文件复制

9. 更多

Python Cookbook 3rd Edition Documentation
Python中文指南
Python黑魔法手册

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
廖雪峰 Java 教程 Java教程 Java快速入门 Java简介 安装JDK 第一个Java程序 Java代码助手 使用IDE 使用IDE练习插件 Java程序基础 Java程序基本结构 变量和数据类型 整数运算 浮点数运算 布尔运算 字符和字符串 数组类型 流程控制 输入和输出 if判断 switch多重选择 while循环 do while循环 for循环 break和continue 数组操作 遍历数组 数组排序 多维数组 命令行参数 面向对象编程 面向对象基础 方法 构造方法 方法重载 继承 多态 抽象类 接口 静态字段和静态方法 包 作用域 classpath和jar 模块 Java核心类 字符串和编码 StringBuilder StringJoiner 包装类型 JavaBean 枚举类 BigInteger BigDecimal 常用工具类 异常处理 Java的异常 捕获异常 抛出异常 自定义异常 使用断言 使用JDK Logging 使用Commons Logging 使用Log4j 使用SLF4J和Logback 反射 Class类 访问字段 调用方法 调用构造方法 获取继承关系 动态代理 注解 使用注解 定义注解 处理注解 泛型 什么是泛型 使用泛型 编写泛型 擦拭法 extends通配符 super通配符 泛型和反射 集合 Java集合简介 使用List 编写equals方法 使用Map 编写equals和hashCode 使用EnumMap 使用TreeMap 使用Properties 使用Set 使用Queue 使用PriorityQueue 使用Deque 使用Stack 使用Iterator 使用Collections IO File对象 InputStream OutputStream Filter模式 操作Zip 读取classpath资源 序列化 Reader Writer PrintStream和PrintWriter 日期与时间 基本概念 Date和Calendar LocalDateTime ZonedDateTime DateTimeFormatter Instant 最佳实践 单元测试 编写JUnit测试 使用Fixture 异常测试 条件测试 参数化测试

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值