学习笔记——Python:第二阶段(ToDo)

笔记目录

      • 1. 数据结构
          • 1.1. 元祖
          • 1.2. 列表(list)
          • 1.3. 集合
          • 1.4. 字典
      • 2. 函数式编程
          • 2.1. 定义函数
          • 2.2. 函数参数
          • 2.3. 函数返回值
          • 2.4. 函数变量作用域
          • 2.5. 生成器
          • 2.6. 嵌套函数
          • 2.7. 函数式编程基础
      • 3. 面向对象编程
          • 3.1. 面向对象概述
          • 3.2. 面向对象三个基本特性
          • 3.3. 类和对象
            • 3.3.1. 定义类
            • 3.3.2. 创建和使用对象
            • 3.3.3. 实例变量
            • 3.3.4. 类变量
            • 3.3.5. 构造方法
            • 3.3.6. 实例方法
            • 3.3.7. 类方法
            • 3.3.8. 静态方法
          • 3.4. 封装性
            • 3.4.1. 私有变量
            • 3.4.2. 私有方法
            • 3.4.3. 定义属性
          • 3.5. 继承性
            • 3.5.1. 继承概念
            • 3.5.2. 重写方法
            • 3.5.3. 多继承
          • 3.6. 多态性
          • 3.7. Python根类——object
          • 3.8. 枚举类
      • 4. 异常处理
      • 5. 常用模块
      • 6. 正则表达式
      • 7. 文件操作与管理

1. 数据结构

数据结构主要包括:数组(Array)、集合(Set)、列表(List)、队列(Queue)、链表(Linkedlist)、树(Tree)、堆(Heap)、栈(Stack)和字典(Dictionary)等
Python中数据容器主要有:序列、集合和字典

注意:Python中没有数组结构

序列(sequence)

  • 序列特点:可迭代的、有序的、元素可以重复
  • 序列包括的结构有:列表(list)、字符串(str)、元祖(tuple)、范围(range)和字节序列(bytes)
  • 序列可进行的操作有:索引、分片、加和乘
    序列的分片(Slicing)就是从序列中且分出小的子序列,分片运算符有两种形式:
    [start:end]start是开始索引,end是结束索引
    [start:end:step]start是开始索引,end是结束索引,step是步长。步长可以为正整数,也可以为负整数。
    因此可用于倒置序列:a = a[::-1]
1.1. 元祖
  • 元组:一种不可变的序列,一旦创建不可以修改
    创建元素可以使用tuple([iterable])函数或者直接用逗号,将元素分割

  • 访问元组:索引访问元素、分片、拆包(Unpack)

    a = ('Hello','World',1,2,3)
    str1,str2,*n = a	# 拆包
    # str1 = 'Hello'
    # str2 = 'World'
    # n = [1,2,3]	# 列表
    
  • 遍历元组:遍历序列一般都是用for循环

    a = (5,4,3,2,1)
    for idx, item in enumerate(a):
    	print("{0} - {1}".format(idx,item ))
    
1.2. 列表(list)

也是一种序列,与元组的区别是:元素无法修改,而列表可修改,包括追加、删除、替换和插入

  • 列表创建
    list([iterable])函数,或者用中括号[]将元素包裹,元素之间用逗号,分隔

  • 追加元素
    append()方法:追加单个元素
    +运算符或extend()方法:追加另外一个列表

  • 插入元素
    list.insert(i, x)i指要插入的索引,x是要插入的元素

  • 替换元素

  • 删除元素
    remove(x)方法,x是要删除的元素,如果没有x元素,会抛出异常
    pop()方法,pop(i)删除i索引值,pop()删除最后面的元素,有 返回值:删除的元素

  • 其他常用方法
    reverse():倒置列表
    copy():复制列表
    clear():清除列表中的所有元素
    index(x[,i[,j]]):返回查找x第一次出现的索引,i是开始查找索引,j是结束查找索引
    count(x):返回x出现的次数

  • 列表推导式

    n_list = [x ** 2 for x in range(10) if x % 2 == 0]
    print(n_list)
    
    # 相当于
    n_list = []
    for x in range(10):
    	if x % 2 == 0:
    		n_list.append(x ** 2)
    print(n_list)
    
    # 多个条件时
    n_list = [x for x in range(100) if x % 2 == 0 if x % 5 == 0]
    n_list = [x for x in range(100) if x % 2 == 0 and x % 5 == 0]
    
1.3. 集合
  • 集合的特点:集合中的元素是无序的、不能重复的。包含可变集合和不可变集合

  • 创建可变集合
    set([iterable])函数,或者用大括号{}

  • 修改可变集合
    add(elem):添加元素,如果元素已经存在则不能添加,且不会抛出错误
    remove(elem):删除元素,如果元素不存在,则抛出错误
    discard(elem):删除元素,如果元素不存在,不会抛出错误
    pop(elem):删除返回集合中的任意一个元素,返回值是删除的元素
    clear():清除集合

  • 遍历集合for in

  • 不可变集合
    frozenset([iterable])函数,不能使用大括号{}

    student_set = frozenset(['张三','李四','王五','王五'])
    
  • 集合推导式

    n_set = {x ** 2 for x in range(10) if x % 2 == 0}
    print(n_set)
    
1.4. 字典

dict是可以迭代的、可变对象

  • 创建字典
    dict()函数,或者用大括号{}将“键:值”对包裹,“键:值”对之间用逗号分隔

    dict1 = {102: '张三', 105: '李四', 109: '王五'}
    print(dict1)
    
    dict2 = dict(S102='张三', S105='李四', S109='王五')
    print(dict2)
    
    print(dict1[102])
    print(dict2['S102'])
    

    注意:特殊形式创建dict(key1=value1,key2=value2,key3=value3...)key必须是字符串,而且字符串要省略单引号或双引号

  • 修改字典
    ①添加
    ②替换
    ③删除:del语句、pop(key[,default])方法和popitem()方法

    dict1 = {102: '张三', 105: '李四', 109: '王五'}
    del dict1[109]
    dict1.pop(105)
    dict1.popitem()	# 随机删除
    
  • 访问字典
    get(key[,default]):通过键返回值,如果键不存在返回默认值
    items():返回字典的所有键值对
    keys():返回字典键视图
    values():返回字典值视图

  • 遍历字典

    dict1 = {102: '张三', 105: '李四', 109: '王五'}
    for k in dict1.keys():
    	print(k)
    
    for v in dict1.values():
    	print(v)
    
    for id, name in dict1.items():
    	print(id, name)
    
  • 字典推导式

    input_dict = {'one': 1, 'two': 2, 'three': 3, 'four': 4}
    
    output_dict = {k: v for k, v in input_dict.items() if v % 2 == 0}
    print(output_dict)
    
    output_dict = [k for k, v in input_dict.items()]
    print(output_dict)
    

2. 函数式编程

内置函数Built-in Functions,缩写BIF):Python官方提供

2.1. 定义函数
def 函数名(参数列表):
	函数体
	return 返回值	# 没有数据返回可省略

def rectangle_area(width, height):
	area = width * height
	return area

r_area = rectangle_area(320.0, 480.0)
print(r_area)
2.2. 函数参数
  • 使用关键字参数调用函数

    def print_area(width, height):
    	area = width * height
    	print('{0} * {1} 长方形的面积是{2}'.format(width, height, area))
    
    print_area(width=320.0, height=480.0)
    
  • 参数默认值

    def make_coffee(name="卡布奇诺"):
    	return "制作一杯{0}咖啡".format(name)
    
    coffee1 = make_coffee("拿铁")
    coffee2 = make_coffee()
    print(coffee1)
    print(coffee2)
    
  • 可变参数
    Python中可变参数有两种,在参数前加***形式,*可变参数在函数中被组装成为一个元组,**可变参数在函数中被组装成为一个字典
    *可变参数

    def sum(*numbers, multiple=1):
    	total = 0.0
    	for number in numbers:
    		total += number
    	return total * multiple
    
    print(sum(100.0, 20.0, 30.0))
    print(sum(30.0, 80.0, multiple=2))
    
    d_tuple = (50.0, 60.0, 0.0)
    print(sum(30.0, 80.0, *d_tuple))
    

    **可变参数

    def show_info(sep=":", **info):
    	print("---------------")
    	for key, value in info.items():
    		print("{0} {2} {1}".format(key, value, sep))
    
    show_info("->", name="Tony", age=18, sex=True)
    
2.3. 函数返回值
  • 无返回值函数
    return None

  • 多返回值函数:返回元组类型数据,元组是不可变的,比较安全

    def position(dt, speed):
    	posx = speed[0] * dt
    	posy = speed[1] * dt
    	# return (posx, posy)
    	return posx, posy
    
    move = position(60.0, (10, -5))
    print(move)
    
2.4. 函数变量作用域

变量可以在模块中创建,作用域是整个模块,称为全局变量
变量也可以在函数中创建,默认情况下作用域是整个函数,称为局部变量

# 全局变量x
x = 20

def print_value():
	global x	# 声明调用全局变量
	x = 10
2.5. 生成器

在一个函数中使用return关键字返回数据,但是有时候会使用yield关键字返回数据。yield关键字的函数返回的是一个生成器(generator)对象,生成器对象是一种可迭代对象。通过__next__()方法获得元素。

# def square(num):
# 	n_list = []
# 	for i in range(1, num + 1):
#		n_list.append(i * i)
#
#	return n_list

def square(num):
 	for i in range(1, num + 1):
		yield i * i

for i in square(5):
	print(i, end=' ')

yield语句可以返回一个元素,此时的函数返回的生成器对象,生成器对象是一种特殊迭代对象。

注意:生成器特别适合用于遍历一些大序列对象,它无须将对象的所有元素都载存入内存后才开始进行操作。而是仅在迭代至某个元素时才会将该元素载放入内存。

2.6. 嵌套函数

函数还可以定义在另外的函数体中,称作“嵌套函数”。

1、嵌套函数可以访问所在外部函数中的变量,但外部函数不能访问嵌套函数局部变量。
2、不能在外部函数体之外直接访问嵌套函数。

def calculate(n1, n2, opr):
	multiple = 2

	# 定义相加函数
	def add(a, b):
		return (a + b) * multiple

	# 定义相减函数
	def sub(a, b):
		return (a - b) * multiple

	if opr == '+':
		return add(n1, n2)
	else:
		return sub(n1, n2)

print(calculate(10, 5, '+'))
print(calculate(10, 5, '-'))
2.7. 函数式编程基础

函数式编程(functional programming)与面向对象编程一样都是一种编程范式,函数式编程,也称为面向函数的编程。
函数式编程所能处理的是一些计算,处理数据

  • 函数类型
    所有函数都有函数类型,函数类型实例与普通类型实例,使用的场景是一样的:可以赋值给一个变量;可以作为一个参数使用;也可以作为函数的返回值使用。

    def calculate_fun(n1, n2, opr):
    	multiple = 2
    
    	# 定义相加函数
    	def add(a, b):
    		return (a + b) * multiple
    
    	# 定义相减函数
    	def sub(a, b):
    		return (a - b) * multiple
    
    	if opr == '+':
    		return add
    	else:
    		return sub
    
    f1 = calculate_fun('+')
    f2 = calculate_fun('-')
    print(f1(10, 5))
    print(f2(10, 5))
    
  • Lambda表达式
    Lambda表达式本质上是一种匿名函数,匿名函数也是函数,有函数类型,也可以创建函数对象。
    定义Lambda表达式语法如下:
    lambda 参数列表: Lambda体

    def calculate_fun(opr):
        multiple = 2
    
        if opr == '+':
            return lambda a, b: (a + b) * multiple
        else:
            return lambda a, b: (a - b)
    
    
    f1 = calculate_fun('+')
    f2 = calculate_fun('-')
    print(f1(10, 5))
    print(f2(10, 5))
    

    注意:Lambda体部分不能是一个代码块,不能包含多条语句,只有一条语句,语句会计算一个结果返回给Lambda表达式,但是与函数不同的是,不需要使用return语句返回。与其他语言中的Lambda表达式相比,Python中提供Lambda表达式只能处理一些简单的计算。

  • 三大基础函数
    函数编程主要是对数据进行处理:过滤、映射和聚合等。
    Python提供了三个基础函数:filter()map()reduce()

    1、filter()filter(function, iterable)
    返回布尔值,在function函数中编写过滤条件,如果为True的元素被保留,如果为False的元素被过滤掉。filter函数返回一个列表。

    users = ['Tony', 'Tom', 'Ben', 'Alex']
    users_filter = filter(lambda u: u.startswith('T'), users)
    
    print(list(users_filter))
    
    number_list = range(1, 11)
    number_filter = filter(lambda it: it % 2 == 0, number_list)
    
    print(list(number_filter))
    

    2、map()map(function, iterable)
    映射操作,可以对可迭代对象的元素进行变化。

    users = ['Tony', 'Tom', 'Ben', 'Alex']
    users_map = map(lambda u: u.lower(), users)
    print(list(users_map))
    

    3、reduce()reduce(function, iterable)
    聚合操作中最基础的是归纳函数reduce(),会将多个数据按照指定的算法积累叠加起来,最后输出一个数据。

    from functools import reduce
    
    a = (1, 2, 3, 4)
    a_reduce = reduce(lambda acc, i: acc + i, a)	# acc是初始值
    print(a_reduce)
    

3. 面向对象编程

3.1. 面向对象概述

面向对象的编程思想:按照真实世界客观事物的自然规律进行分析,客观世界中存在什么样的实体,构建的软件系统就存在什么样的实体。

3.2. 面向对象三个基本特性
  • 封装性:封装能够使外部访问者不能随意存取对象的内部数据,隐藏了对象的内部细节,只保留有限的对外接口。外部访问者不用关心对象的内部细节,使得操作对象变得简单。

  • 继承性:特殊类拥有一般类的全部数据和操作,称为特殊类继承一般类。一般类称为“父类”或“超类”,特殊类称为“子类”或“派生类”,为了统一,本书一般类统称为“父类”,特殊类统称为“子类”。
    Python、C++支持多继承。
    Java、Swift、OC都只支持单继承。

  • 多态性:多态性是指在父类中成员被子类继承之后,可以具有不同的状态或表现行为。

3.3. 类和对象
3.3.1. 定义类

Python中一个类的实现包括:类定义和类体。

class 类名[(父类)]:
	类体

class Animal(object):
   	# 类体
   	# 类的成员
   	pass

提示:代码的pass语句什么都不做,用于维持结构的完整。

3.3.2. 创建和使用对象

对象也称为实例。一个对象生命周期:创建对象、使用对象和销毁对象。
销毁对象:Python中程序员不用释放对象内存。
创建对象:通过构造方法,Animal()
使用对象:anim = Animal()anim是指向对象的引用。

anim = Animal()
print(anim)

提示:__str__()这种双下划线开始和结尾的方法,是Python保留的,有着特殊的含义,称为魔法方法。

3.3.3. 实例变量

提示:在Python类成员中有attribute(成员变量)和property(属性)。

attribute是类中保存数据的变量,如果需要对attribute进行封装,那么在类的外部为了访问这些attribute,往往会提供一些settergetter访问器,setter访问器是对attribute赋值的方法,getter访问器是取attribute值的方法,这些方法在创建和调用都比较麻烦,于是Python又提供了propertyproperty本质上就是settergetter访问器,是一种方法。

实例变量:某个个体实例的变量。

class Animal(object):

    def __init__(self, age, sex, weight):
        self.age = age
        self.sex = sex
        self.weight = weight


anim = Animal(2, 1, 10.0)
print(anim.age, anim.sex, anim.weight)
3.3.4. 类变量

类变量是所有实例(或对象)共有的变量。

class Account:
    # 利率 创建类变量
    interest_rate = 0.0668

    def __init__(self, owner, amount):
        self.owner = owner
        self.amount = amount


account = Account('Tony', 10000)
print(account.owner, account.amount)
print(Account.interest_rate)

注意:不要通过实例存取类变量数据。当通过实例读取变量时,首先Python解释器会先在实例中找这个变量,如果没有再到类中去找;当通过实例为变量赋值时,无论类中是否有同名变量,Python解释器会创建一个同名实例变量。

3.3.5. 构造方法

__init__()构造方法,用来初始化类中实例变量。

3.3.6. 实例方法

实例方法与实例变量类似,属于类的某个个体的方法。
第一个参数self,当前实例与该方法绑定了,所以该方法就是实例方法。

class Animal(object):

    def __init__(self, age, sex=1, weight=8.0):
        self.age = age
        self.sex = sex
        self.weight = weight

    def eat(self):
        self.weight += 0.05
        print('eat...')

    def run(self):
        self.weight -= 0.01
        print('run...')


anim = Animal(2, 1, 10.0)
print(anim.__dict__)
anim.eat()
print(anim.__dict__)
anim.run()
print(anim.__dict__)
3.3.7. 类方法

类方法与类变量是类似的,都属于类,不属于类的个体。类方法不需要与实例进行绑定,第一个参数不是self,但是它需要类绑定,第一个参数是type类型,type是描述数据类型的类。

@classmethod@表示装饰器,是Python 3提供的,修饰方法、函数、类,起到约束的作用。

class Account:
    # 利率 创建类变量
    interest_rate = 0.0668
    
    # 类方法
    @classmethod
    def interest_by(cls, amt):
        print(type(cls))
        return cls.interest_rate * amt


ints = Account.interest_by(12_000)
print(ints)

注意:类方法中可以访问其他的类变量和类方法,但是不能访问实例变量和实例方法。

3.3.8. 静态方法

类中定义方法,既不想与类绑定,也不想与实例绑定,这种方法就是静态方法。

总结:静态方法与类方法在很多场景是类似的,只是在定义时有一些区别,类方法需要绑定类,静态方法不需要绑定类,静态方法与类的耦合度更加松散。在一个类中定义静态方法,只是为了提供一个基于类名的命名空间

class Account:
    # 利率 创建类变量
    interest_rate = 0.0668

    # 类方法
    @classmethod
    def interest_by(cls, amt):
        print(type(cls))
        return cls.interest_rate * amt

    # 静态方法
    @staticmethod
    def interest_with(amt):
        # return Account.interest_rate * amt
        return Account.interest_by(amt)	# 可调用类方法


ints = Account.interest_with(12_000)
print(ints)
3.4. 封装性
3.4.1. 私有变量

默认声明的变量是公用的,私有变量就是在变量前加双下划线(__)。

提示:Python中并没有严格意义上的封装,所谓的私有变量只是形式上的限制,如果想在类的外部访问这些私有变量也是可以的,这些双下划线(__)开头的私有变量,其实只是换了一个名字,他们的命名规律为“_类名__变量”,所以如a1.weight改成a1._Animal__weight就可以访问了,但这种访问方式并不符合规范,会破坏封装。

3.4.2. 私有方法

私有方法封装与私有变量是类似的,就是在方法前加双下划线(__)。

3.4.3. 定义属性

面对对象设计:一个类是不应该有公有的实例成员变量的,这些实例成员变量应该被设计为私有的,然后通过公有的settergetter访问器访问。

class Animal(object):

    def __init__(self, age, sex=1, weight=0.0):
        self.age = age
        self.sex = sex
        self.__weight = weight

    def set_weight(self, weight):
        self.__weight = weight

    def get_weight(self):
        return self.__weight


anim = Animal(2, 1, 10.0)
anim.set_weight(10.3)
print(anim.get_weight())

这可以通过定义属性(property)实现。定于属性可以使用@property@属性名.setter装饰器@property用来修饰getter访问器,@属性名.setter用来修饰setter访问器。

class Animal(object):

    def __init__(self, age, sex=1, weight=0.0):
        self.age = age
        self.sex = sex
        self.__weight = weight

	# 须先定义getter访问器
    @property
    def weight(self):
        return self.__weight

    @weight.setter
    def weight(self, weight):
        self.__weight = weight


anim = Animal(2, 1, 10.0)
anim.weight = 10.3
print(anim.weight)
3.5. 继承性
3.5.1. 继承概念
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def info(self):
        template = 'Person [name={0}, age={1}]'
        s = template.format(self.name, self.age)
        return s


# class Student:
#     def __init__(self, name, age, school):
#         self.name = name
#         self.age = age
#         self.school = school
#
#     def info(self):
#         template = 'Person [name={0}, age={1}, school={2}]'
#         s = template.format(self.name, self.age, self.school)
#         return s

class Student(Person):

    def __init__(self, name, age, school):
        super().__init__(name, age)
        self.school = school


stu = Student('Tony', 20, '清华大学')
print(stu.info())
3.5.2. 重写方法

子类中有与父类具体相同的方法名,而且方法的参数也相同。子类就会重写(Override)父类方法。

class Student(Person):

    def __init__(self, name, age, school):
        super().__init__(name, age)
        self.school = school

    def info(self):
        template = 'Person [name={0}, age={1}, school={2}]'
        s = template.format(self.name, self.age, self.school)
        return s


stu = Student('Tony', 20, '清华大学')
print(stu.info())
class Animal(object):
    """定义动物类"""

    def __init__(self, age, sex=1, weight=0.0):
        self.age = age
        self.sex = sex
        self.weight = weight

    def eat(self):
        self.weight += 0.05
        print('动物吃...')


class Dog(Animal):
    def eat(self):
        self.weight += 0.1
        print('狗狗吃...')


a1 = Dog(2, 0, 10.0)
a1.eat()
3.5.3. 多继承

多继承可能会发生命名冲突

Python支持多继承,但Python给出了解决名字冲突的方案。这个方案是当子类实例调用一个方法时,先从子类中查找,如果没有找到则查找父类。父类的查找顺序是按照子类声明的父类列表从左到右查找,如果没有找到再找父类的父类,依次查找下去。

3.6. 多态性
3.7. Python根类——object
3.8. 枚举类

4. 异常处理

5. 常用模块

6. 正则表达式

7. 文件操作与管理

你可能感兴趣的:(学习笔记)