Python编程进阶

=================【Python基础教程】===========

5、函数

函数是一段组织好的、能够重复使用的,用来实现单一或相关功能的代码段。
函数能提升应用的模块性,提升代码的利用率。
复制代码

1. 自定义函数

1.1 函数语法

def 函数名(参数):
	...
	函数体
	...
	
# 自定义函数
def custom_func(elem):
    print("这是个人自定义函数...")
    print("我是参数elem: ", elem)

# 函数调用
custom_func(1)
复制代码

1.2 函数的参数

1.2.1 普通参数

def common_parameter(par1, par2):       # 函数定义,形参,提供给使用者一个接口
    print(par1)
    print(par2)

common_parameter(11, 22)    # 函数调用,实参,实参值传递给形参
复制代码

1.2.2 默认参数

# par_default为函数的默认参数,函数调用时若是不传值的话,就是用默认的参数的值;若是传值了就用传的值
def default_parameter(par1, par2, par_default="我是默认值"):
    print("..........default parameter..........")
    print(par1)
    print(par2)
    print(par_default)

default_parameter("我是par1", 222)
default_parameter(111, 222, "test")
default_parameter(par_default="位置参数生效", par1=1111, par2=True)
复制代码

1.2.3 动态参数

# (1) 能够接受任意个参数
# (2) 动态参数有两种:*args和**kwargs,*args必须在*kwargs的前面
# *args: 接受的是按照位置传参的值,组织成一个 **元组**
# **kwargs: 接受的是按照关键字传参的值,组成一个 **字典**
# (3) 参数的传递顺序:位置参数、*args、默认参数、**kwargs
def dynamic_parameter(par1, par2, *args, par_default="default", **kwargs):
    print(".......dynamic parameter.......")
    print(par1)
    print(par2)
    print(args)
    print(par_default)
    print(kwargs)
    print(kwargs['name'])
    print(kwargs['age'])
    

dynamic_parameter(1, 2, 2, 3, 4, 5, par_default=5, name='kwargs', age=12)
复制代码

1.3 函数的返回值

# return 语句用于退出函数,选择性地向调用方式返回一个表达式。不带参数值的return语句返回None。
def return_func(a, b):
    total = a + b
    print("函数内:", total)
    return total


total_exc = return_func(12, 23)
print("函数外:", total_exc)
复制代码

2. 异常处理

  异常就是程序执行时发生错误的信号,Python中不一样异经常使用不一样类对象标识不一样的异常,一个异常标识一种错误。python

  Python程序执行时,检测到一个错误时,若是不处理程序就在当前异常处终止。编写特定的异常处理代码专门来处理异常,若是捕捉成功则进入定制的另外一个程序分支,使程序不崩溃。因此在程序中必须提供一种异常处理机制来加强程序的健壮性和容错性,提升用户体验。git

2.1 常见异常类:

(1) AttributeError          访问的对象没有该属性
(2) IOError                 输入/输出异常,基本上是没法打开文件
(3) ImportError             没法引入模块或包,基本是路径或名称错误
(4) IndentationError        语法错误,代码没有正确对齐
(5) IndexError              下标索引超出边界
(6) KeyError                访问的字典里面不存在的键
(7) KeyboardInterrupt       Ctrl + c 被按下
(8) NameError               访问一个还未被赋予对象的变量
(9) SyntaxError             Python代码非法,代码不能编译
(10) TypeError              传入对象类型与要求的不符合
(11) ValueError             传入一个调用者不指望的值
(12) UnboundLocalError      访问一个还未被设置的局部变量,基本上是因为另有一个同名的全局变量
(13) AssertionError         断言错误,说明断言的条件为假
(14) ..............
复制代码

2.2 异常处理方式

2.2.1 try...exception...finally

GitHub代码commits id:a7df219程序员

list_exception = [1, 2, 3]

try:
    for i in list_exception:
        print(list_exception[i+2])

    raise TypeError('....主动抛出异常...')
except IndexError as e:
    print("异常 %s 已经在这里被捕获了,下面再有异常处理就再也不被捕获了" % e)
except Exception as e:
    print(e)
finally:
    print("程序执行结束,无论异常是否被捕获,这里必定始终会执行")
复制代码

2.2.2 try...exception...else

GitHub代码commits id:47da104github

else_exception = [1, 2, 3]
try:
    for i in [1, 4]:
        print(i)
except IndexError as e:
    print(e)
except SyntaxError as se:
    print(se)
else:
    print("只有再try语句里面的执行成功的时候,才会执行else里面的内容")
复制代码

2.3 自定义异常

GitHub代码commits id:e8936a9express

class EvaException(BaseException):
    def __int__(self, msg):
        self.msg = msg

    def __str__(self):
        return self.msg


try:
    raise EvaException("自定义错误")
except EvaException as e:
    print(e)
复制代码

2.4 断言

  assert断言是声明其布尔值必须为真的断定,若是发生异常则说明表达式为假。 【GitHub代码commits id:b4641c编程

assert 1 == 1
try:
    assert 1 == 2
except AssertionError as e:
    print("看见我说明断言的判断条件是错误的,这个异常已经被我捕获了: %s" % e)
复制代码

3. 迭代器

  迭代器 指的是迭代取值的工具,迭代是一个重复的过程,每一次的重复都是基于上一次的结果而进行的;迭代提供了不依赖于索引而进行取值的方法。数组

  可迭代对象 但凡内置 _iter_ 方法的对象,都称之为可迭代对象。Python常见数据类型中,str、list、tuple、dict、set、文件对象都是可迭代对象。缓存

  迭代器对象 (1)既内置 __next__方法,(2)又有 __iter__方法的对象,执行迭代器的 _iter_ 方法获得的依然是迭代器对象自己,执行 _next_ 方法能够不依赖索引进行取值。bash

  总的来讲: 迭代器必定是可迭代对象,而可迭代对象不必定是迭代器。app

3.1 判断可迭代对象和迭代器

from collections.abc import Iterable, Iterator

string1 = "Iterable"
list1 = range(10)
if isinstance(string1, Iterable):
    print("该对象是可迭代对象")
elif isinstance(string1, Iterator):
    print("该对象是迭代器")
else:
    print("您的判断不存在")
复制代码

3.2 迭代对象的使用

list1 = range(5)
for i in list1:
    print(i)
# 将 "可迭代对象" 转换成 "迭代器对象"
if isinstance(list1, Iterable):
    print("该对象是可迭代对象")
elif isinstance(list1, Iterator):
    print("该对象是迭代器")
else:
    print("您的判断不存在")
list2 = iter(list1)
try:
    print("迭代器对象获取数据:", next(list2))
    print("迭代器对象获取数据:", next(list2))
    print("迭代器对象获取数据:", next(list2))
    print("迭代器对象获取数据:", next(list2))
    print("迭代器对象获取数据:", next(list2))
    print("迭代器对象获取数据:", next(list2))
except StopIteration as e:
    print("That is all folks!")
复制代码

4. 生成器

  受内存的限制,咱们若是要用列表生成式生成一个比较大的列表的时候就棘手了。生成器是一个特殊的程序,能够被用做控制循环的迭代行为,Python中生成器是迭代器的一种,使用yield返回值函数,每次调用yield会暂停,而可使用next()和send()函数恢复生成器。生成器一次只返回一个值。

4.1 建立生成器

l1 = [x*x for x in range(10)]
print("列表生成式l1: ", l1)
g1 = (x*x for x in range(5))
print("生成器g1: ", g1)
try:
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
    print("生成器迭代值:", next(g1))
except StopIteration as e:
    print("生成器全部的值已经迭代结束了......")
复制代码

4.2 斐波拉契数列

# 0 1 1 2 3 5 8 13 21
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a+b
        n = n + 1
    return "done"


g = fib(5)
while True:
    try:
        x = next(g)
        print("......: ", x)
    except StopIteration as e:
        print("生成器已迭代完毕...", e.value)
        print("生成器已迭代完毕...", e.args)
        break
复制代码

5. 装饰器

  Python的装饰器(decorators)就是用来拓展原来函数功能的一种函数,目的是不改变原函数名(或类名)的状况下,给函数增长新的功能。

5.1 装饰器入门

  已开发哔哩哔哩APP为例,前期开发了我的空间、我的关注、钱包等功能,这些功能的访问的必须和我的帐号的登陆状态是挂钩的。若是不登陆直接访问这些功能的话就会收到权限限制的提示。这些不一样的功能又是由不一样的程序员开发的,权限验证是由公共部门开发的,权限保密权限涉密等级又比较高,不能全员皆知。

  装饰器的引入就能够完美的解决这个问题。公共部门开发权限认证装饰器,须要调用权限认证的功能只需调用装饰器便可。

  装饰器的就是让你在一个函数的先后去执行代码。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
""" @File : 55_decorators.py @Time : 2019/10/8 16:07 @Author : Crisimple @Github : https://crisimple.github.io/ @Contact : Crisimple@foxmail.com @License : (C)Copyright 2017-2019, Micro-Circle @Desc : None """

def authority(function_to_decorate):
    def auth():
        username = input("请输入用户名:")
        password = input("请输入用户密码:")
        if username == 'crisimple' and password == '123456':
            print("......认证成功......")
            function_to_decorate()
        else:
            print("......认证失败......")
    return auth

@authority
def view_space():
    print("......欢迎进入哔哩哔哩我的空间......")


if __name__ == "__main__":
    view_space()
    print("view_space.__name__ is: ", view_space.__name__)
复制代码

5.2 装饰器应用

(1)引入日志
    (2)函数执行时间统计
    (3)执行函数前于谦准备
    (4)执行函数后的清理工做【测试固件运用】
    (5)权限校验等场景【登陆/权限限制】
    (6)缓存
复制代码

5.3 带固定参数的装饰器

GitHub示例

def message_auth(function_to_decorate):
    def auth(user, passwd):
        username = input("请输入用户名:")
        password = input("请输入用户密码:")
        if username == user and password == passwd:
            print("......认证成功......")
            function_to_decorate(user, passwd)
        else:
            print("......认证失败......")
    return auth

@message_auth
def message(user, passwd):
    print("......您能够查看您的消息了......")
复制代码

5.4 无固定参数的装饰器

GitHub示例

def pay_auth(function_to_decorate):
    def auth(*args, **kwargs):
        input("=====请输入你的动态口令=====: ")
        function_to_decorate(*args, **kwargs)
    return auth

@pay_auth
def pay(a, b, c):
    print("......您的帐户余额为动态口令之和:%s" % (a+b+c))
复制代码

5.5 多个装饰器装饰同一函数

GitHub示例

# 对于Python中的”@”语法糖,装饰器的调用顺序与使用 @ 语法糖声明的顺序相反。
def first_decorator(function_to_decorator):
    def wrapper():
        print("This is first decorator01")
        function_to_decorator()
        print("End of the first decorator01")
    return wrapper

def second_decorator(function_to_decorator):
    def wrapper():
        print("This is second decorator02")
        function_to_decorator()
        print("End of the second decorator02")
    return wrapper

@first_decorator
@second_decorator
def func_decorator():
    print("...【This is to be decorated function】...")
复制代码

5.6 Python内置装饰器

在Python中有三个内置的装饰器,都是跟class相关的:staticmethod、classmethod 和property。

(1)staticmethod 是类静态方法,其跟成员方法的区别是没有 self 参数,而且能够在类不进行实例化的状况下调用
(2)classmethod 与成员方法的区别在于所接收的第一个参数不是 self (类实例的指针),而是cls(当前类的具体类型)
(3)property 是属性的意思,表示能够经过经过类实例直接访问的信息,对于一个类的属性,python的访问是没有限制的,但有时候咱们须要对属性的访问加以限制,property能够胜任
复制代码

GitHub示例

class Foo(object):
    def __init__(self):
        self.name = 'zha nan'
        self.age = '23'

    # 不用传递self对象,就至关因而个普通方法
 @staticmethod
    def direct_call():
        print("类静态方法,能够在类不进行实例化的状况下调用,能够不用传self参数了,看到这句话就说明了这个道理")

    # 使用classmethod装饰器装饰后,方法的第一个参数是类对象;调用类方法不须要建立类的实例。classmethod也是一个类,因此classmethod是一个类装饰器。
 @classmethod
    def class_method(cls):
        print(cls.direct_call)

    # 对于一个类的属性,python的访问是没有限制的,但有时候咱们须要对属性的访问加以限制,property能够胜任
    # property是一个类,它有三个方法,deleter,setter,getter,有两种使用方式。
 @property
    def name(self):
        return self.name

 @name.setter
    def name(self, set_num):
        return self.name == set_num

 @name.deleter
    def name(self):
        del self.name


from abc import abstractclassmethod, ABCMeta
# 一个类中的任何方法被abstractmethod装饰后,这个类不能实例化而且子类必须实现被abstractmethod装饰的方法
class ChildFoo(abstractmethod=ABCMeta):
 @abstractclassmethod
    def eat(cls):
        pass
复制代码

6. Python的内置函数

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
""" @File : 56_builtIn_function.py @Time : 2019/10/15 18:45 @Author : Crisimple @Github : https://crisimple.github.io/ @Contact : Crisimple@foxmail.com @License : (C)Copyright 2017-2019, Micro-Circle @Desc : None """

# 1. abs() --- 返回数字的绝对值
a11 = 1
a12 = -2
a13 = 0
print("%s 的绝对值为 %s" % (a11, abs(a11)))
print("%s 的绝对值为 %s" % (a12, abs(a12)))
print("%s 的绝对值为 %s" % (a13, abs(a13)))
print("\n")
# --------------------------------
# bin() --- 返回一个整数int或长整型long int的二进制表示
bin_1 = 10
bin_2 = 20
print("%s通过bin后返回%s" % (bin_1, bin(10)))
print("%s通过bin后返回%s" % (bin_2, bin(20)))
print("\n")
# --------------------------------
# max() --- 返回给定参数的最大值,参数能够为序列
print("返回序列的最大值:", max(100, 200, 3000, 800))
print("\n")
# --------------------------------
# min() --- 返回给定参数的最小值,参数能够为序列
print("返回序列的最小值:", min(-100, 200, 0, -10000))
print("\n")
# ---------------------------------
# reversed() --- 用于反向列表元素
reverse_list = [3, 5, 7, 1]
reversed_tuple = (1, 4, 3, 5)
reverse_list.reverse()
print("%s 的反向输出为:%s" % (reverse_list, reverse_list))
# print("%s 的反向输出为:%s" % (reversed_tuple, reversed_tuple))
print("\n")
# -----------------------------
# oct() --- 将一个整数转换成8进制字符串
print("返回八进制的字符串:", oct(10))
# -----------------------------
# zip() --- 函数用于将可迭代的对象做为参数,将对象中对应的元素打包成一个个元组,而后返回由这些元组组成的列表。
# 若是各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操做符,能够将元组解压为列表。
zip_1 = [1, 2, 3]
zip_2 = [4, 5, 6]
zip_3 = [7, 8, 9]
zipped1 = zip(zip_1, zip_2)
zipped2 = zip(zip_3, zip_2)
print("压缩成数组:", zipped1)
print("解压数组:", zip(*zipped2))
print("\n")
# -----------------------------
# complex([real[, imag]]) 建立一个值为 real + imag * j 的复数或者转化一个字符串或数为复数。若是第一个参数为字符串,则不须要指定第二个参数
# real -- int, long, float或字符串
# imag -- int, long, float
print("返回一个复数:", complex(1, 2))
print("返回一个复数:", complex("1+2j"))
print("\n")


# 2. divmod() --- 把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)
a21 = -7
b21 = -2
a22 = 0
b22 = 5
a23 = 20
b23 = 0
print("%s 除以 %s 的;返回结果为:%s" % (a21, b21, divmod(a21, b21)))
print("%s 除以 %s 的;返回结果为:%s" % (a22, b22, divmod(a22, b22)))
# print("%s 除以 %s 的;返回结果为:%s" % (a23, b23, divmod(a23, b23)))
print("\n")
# pow(x, y) --- 返回x的y次方的值
c31 = 2
cc31 = -3
c32 = 2
cc32 = 3
print("%s 的 %s 次幂运算为:%s" % (c31, cc31, pow(c31, cc31)))
print("%s 的 %s 次幂运算为:%s" % (c32, cc32, pow(c32, cc32)))
print("\n")
# ---------------------------------------------------------
# sum(iterable[, start]) --- 对一系列数据求和
# iterable --- 可迭代对象:列表、元组、集合
# start --- 指定增长的参数,若是没有设置这个值,默认为0
sum_1 = [0, 1, 2, 3]
sum_2 = (9, 1, 2, 3)
sum_3 = {9, 1, 2, 0}
print("%s 求和结果为:%s" %(sum_1, sum(sum_1)))
print("%s 求和结果为:%s" %(sum_2, sum(sum_2)))
print("%s 求和结果为:%s" %(sum_3, sum(sum_3)))
print("\n")
# --------------------------------------------
# sorted(iterable, cmp=None, key=None, reverse=False)
# iterable -- 可迭代对象
# cmp -- 比较的函数有两个参数,参数的值从可迭代对象中取出,函数必须遵照,大于返回1,小于则返回-1,等于则返回0
# key -- 用来进行比较的元素,只有一个参数,函数的参数取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序
# reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)
sorted_dict = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
print("排序结果为:", sorted(sorted_dict, key=lambda s: s[2], reverse=True))
print("\n")


# 3. input & raw_input
# input() 读取一个合法的 python 表达式,输入字符串时必须引号括起来,不然会引起 SyntaxError
# raw_input() 将全部输入做为字符串看待
# 当实际测试下来两个并无什么区别的感受
# a31 = input("input: ")
# print("输入的数据为 %s, 它的类型为:%s" % (a31, type(a31)))
# a32 = input("raw_input: ")
# print("输入的数据为 %s, 它的类型为:%s" % (a32, type(a32)))


# 4. open() --- 用于打开一个文件,建立一个 file 对象,相关的方法才能够调用它进行读写
# file() --- 用于建立file对象,它有一个别名叫open()
# 打开文件的模式:
# r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
# rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
# r+ 打开一个文件用于读写。文件指针将会放在文件的开头。
# rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
# w 打开并只能写入。若文件已存则打开文件并从头开始编辑,原内容会被删除。若该不存在,建立新文件。
# wb 二进制格式打开文件只用于写入。若文件已存在则打开文件并从头开始编辑,即原有内容会被删除。若是该文件不存在,建立新文件。
# w+ 打开一个文件用于读写。若是该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。若是该文件不存在,建立新文件。
# wb+ 以二进制格式打开文件用于读写。若是该文件已存在则打开文件从开头开始编辑原内容会被删除。若是该文件不存在,建立新文件。
# a 打开文件用于追加。若文件已存在,文件指针放在文件的结尾。新的内容会被写入已有内容。若文件不存在,建立新文件进行写入。
# ab 二进制格式打开文件用于追加。若文件已存文件指针放在文件结尾。新内容会写入到已有内容。若文件不存在,建立新文件进行写入。
# a+ 打开文件用于读写。若文件已存在文件指针将放在文件的结尾。文件打开时会是追加模式。若是该文件不存在,建立新文件用于读写。
# ab+ 以二进制格式打开一个文件用于追加。若是该文件已存在,文件指针将会放在文件的结尾。若是该文件不存在,建立新文件用于读写。
# file对象的方法
# file.read([size]) --- 指定大小读取文件,若不写size,则返回整个文件
# file.readline() --- 返回一行
# file.readlines([size]) --- 返回指定size行,未指定的则返回所有行
# for line in f: print line --- 经过迭代器访问
# f.write["Hello"] --- 写入字符串数据,如果写入其余类型的数据则需先转换成字符串类型,再写入
# f.tell() --- 返回一个整数,表示当前文件指针的位置
# f.seek(偏移量,[起始位置]) --- 用来移动文件指针,偏移量可正可负;起始位置:0-文件头,默认;1-当前位置;2-文件尾
# f.close() --- 关闭文件
with open('55_decorators.py', 'r', encoding='utf-8') as f:
    content = f.readline()
    print(content)
print("\n")


# 5. staticmethod --- 内置装饰器,返回类的静态函数
class StatiClass(object):
 @staticmethod
    def write():
        print("类的静态方法")
StatiClass.write()
print("\n")
# -------------------------------------
# classmethod --- 内置装饰器修饰的函数不须要实例化,第一个参数由self变为cls,用来调用类的属性、类的方法、
class ClassMethod(object):
    bar = 1
    def func1(self):
        print('foo')

 @classmethod
    def func2(cls):
        print(cls.bar)
        cls().func1()

ClassMethod.func2()
print("\n")


# 6. all() --- 判断给定的可迭代对象参数 iterable 中的全部元素是否都为True,若是全是返回True,不是则为False
# 除了0,空,None,False外都算True
a61 = [1, 2, 3, 4, 5]
a62 = [1, '', '2', 'a']
a63 = [1, 0, '2', 'a']
a64 = [1, False, '2', 'a']
print("%s 的返回:%s" % (a61, all(a61)))
print("%s 的返回:%s" % (a62, all(a62)))
print("%s 的返回:%s" % (a63, all(a63)))
print("%s 的返回:%s" % (a64, all(a64)))
print("\n")
# any() --- 判断给定的可迭代参数iterable是否全为False,则返回 False,若是有一个为True则返回True
b61 = [1, 2, 3, 4, 6]
b62 = [0, 2, 3, 4, 6]
b63 = [0, '', False, None]
print("%s 的返回:%s" % (b61, any(b61)))
print("%s 的返回:%s" % (b62, any(b62)))
print("%s 的返回:%s" % (b63, any(b63)))
print("\n")


# 7. enumerate --- 将可遍历的数据对象(列表、元组或字符串)组合成一个索引序列,同时列出数据和数据下表,多用于for循环
# enumerate(sequence, [start=0]) --- sequence(一个序列、迭代器或其余支持迭代对象);start(下标起始位置)
sequence71 = ['A', 'B', 'C']
sequence72 = "I'm a good boy."
sequence73 = (1, 2, 3)
for i, element in enumerate(sequence71):
    print(i, element)
for i, element in enumerate(sequence72):
    print(i, element)
for i, element in enumerate(sequence73):
    print(i, element)
print("\n")
# iter(object[, sentinel]) --- 生成迭代器
iter_1 = [1, 2, 3, 4, 5, 6]
iter_2 = "xiao"
for i in iter_1:
    print("=====%s" % i)
print("**************", next(iter(iter_2)))
print("**************", next(iter(iter_2)))
print("**************", next(iter(iter_2)))
print("**************", next(iter(iter_2)))
print("\n")
# -----------------------------
# next() --- 返回迭代器的下一个项目
next_1 = iter([1, 2, 3, 4])
while True:
    try:
        x = next(next_1)
        print("next访问迭代器的数据:", x)
    except StopIteration:
        break
print("\n")


# 8. int() --- 将一个字符串或数字转换为整型
a81 = 0.1
a82 = 3.8
a83 = -1
a84 = '123'
print("%s 整形为 %s" % (a81, int(a81)))
print("%s 整形为 %s" % (a82, int(a82)))
print("%s 整形为 %s" % (a83, int(a83)))
print("%s 整形为 %s" % (a84, int(a84)))
print("\n")
# str() --- 返回一个对象的string格式
print(str(123))
print(type(str({"A": 1, "B": 2})))
print("\n")
# --------------------------------------------------------------
# tuple() --- 将列表转换为元组
tuple_1 = [1, 2, 3, 7]
print("tuple()将 %s 转换成元组后为:%s" % (tuple_1, tuple(tuple_1)))
print("\n")
# --------------------------------
# list() --- 将元组转换为列表
list_1 = (1, '2', 'xyz', 7)
print("list()将 %s 转换成列表后为:%s" % (list_1, list(list_1)))
print("\n")
# --------------------------------
# slice(start, stop, step) --- 实现切片对象,用在切片操做函数里的参数传递
slice_list = [1, 2, 3, 4, 5, 6, 7]
myslice = slice(1, 6, 2)
print("slice截取列表:", slice_list[myslice] )
print('\n')
# --------------------------------
# dict(**kwarg)
# dict(mapping, **kwarg)
# dict(iterable, **kwarg)
print("字典1:", dict())
print("字典1:", dict(a='1', b=2, c=3))
print("字典1:", dict(zip(['AA', 'BB', 'CC'], [11, 22, 33])))
print("字典1:", dict([("AAA", 111), ('BBB', 222), ('CCC', 333)]))
print("\n")
# --------------------------------
# bool() --- 将给定参数转换为布尔类型,若是没有参数,返回False
bool_1 = 0
bool_2 = 1
bool_3 = None
bool_4 = ''
bool_5 = 'A'
print("bool() 将 %s 转换为bool类型后为:%s" % (bool_1, bool(bool_1)))
print("bool() 将 %s 转换为bool类型后为:%s" % (bool_2, bool(bool_2)))
print("bool() 将 %s 转换为bool类型后为:%s" % (bool_3, bool(bool_3)))
print("bool() 将 %s 转换为bool类型后为:%s" % (bool_4, bool(bool_4)))
print("bool() 将 %s 转换为bool类型后为:%s" % (bool_5, bool(bool_5)))
print("\n")
# --------------------------------
# float() --- 将整数和字符串转换成浮点数
print("整数转换为浮点数:", float(12))
print("字符串转换为浮点数:", float('234'))
print("\n")
# --------------------------------
# set(iterable) --- 建立一个无序不重复的元素集,iterable可迭代对象
# --- 可进行关系测试,删除重复数据,还能够计算并集、交集、差集等
set_1 = set("HELLO")
set_2 = set("WORLD")
print("原集合分别为:%s %s" % (set_1, set_2))
print("%s & %s 的结果为:%s" % (set_1, set_2, set_1 & set_2))
print("%s | %s 的结果为:%s" % (set_1, set_2, set_1 | set_2))
print("%s - %s 的结果为(即前面有后面没有的):%s" % (set_1, set_2, set_1 - set_2))
print("\n")
# --------------------------------
# map(function,iterable,...) --- 会根据提供的函数对指定序列作映射
map_result = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print("map函数返回", map_result)
print("\n")
# --------------------------------
# repr() --- 将对象转换为供解释器读取的形式
repr_dict = {"A": 1, "B": 2}
print("repr返回对象的string形式:", repr(repr_dict))
print("\n")
# --------------------------------
# hash() --- 获取取一个对象(字符串或者数值等)的哈希值
hash_1 = "test hash"
hash_2 = 123
hash_3 = str([1, 2, 3])     # 集合
hash_4 = str(sorted({'A': 1}))
print("%s 的hash值为:%s" % (hash_1, hash(hash_1)))
print("%s 的hash值为:%s" % (hash_2, hash(hash_2)))
print("%s 的hash值为:%s" % (hash_3, hash(hash_3)))
print("%s 的hash值为:%s" % (hash_4, hash(hash_4)))
print("\n")
# --------------------------------
# hex() --- 将10进制整数转换成16进制,以字符串形式表示
print("hex的结果:", hex(255))
print("\n")
# --------------------------------
# bytearray() --- 返回一个新本身数据,数组里的元素是可变的,而且每一个元素的值的范围为 0 <= x < 256
print("bytearray....: ", bytearray([1, 2, 3]))
print("bytearray....: ", bytearray())
print("\n")


# 9. ord() --- 是 chr() 函数(对于8位的ASCII字符串)或 unichr() 函数(对于Unicode对象)的配对函数
print(ord('a'))
print(ord('b'))
print(ord('C'))
# chr() --- 用一个范围在 range(256)内的(就是0~255)整数做参数,返回一个对应的字符。
print(chr(123))
print(chr(97))
# unichr() --- 和 chr()函数功能基本同样, 只不过是返回 unicode 的字符
# print(unichr(97))
print("\n")


# 10. eval() --- 用来执行一个字符串表达式,并返回表达式的值
# eval(expression[, globals[, locals]])
# expression -- 表达式
# globals -- 变量做用域,全局命名空间,若是被提供,则必须是一个字典对象
# locals -- 变量做用域,局部命名空间,若是被提供,能够是任何映射对象
print(eval('3 * 4'))
print(eval('pow(2, 3)'))
print("\n")
# ----------------------------------
# exec 执行储存在字符串或文件中的Python语句,相比于 eval,exec能够执行更复杂的 Python 代码。
exec('print("Hello World")')
print("\n")
# ----------------------------------
# str.format() 字符串格式化功能
print("{} {}".format("Hello", "Python"))
print("{1} {0} {1}".format("Hello", "Python"))
print("冲动的人:{name1}, 喜欢的人:{name2}".format(name1="小徐", name2="where?"))
print("\n")
# -----------------------------------
# compile(source, filename, mode[, flags[, dont_inherit]]) --- 将一个字符串编译为字节代码
# source -- 字符串或者AST(Abstract Syntax Trees)对象
# filename -- 代码文件名称,若是不是从文件读取代码则传递一些可辨认的值。
# mode -- 指定编译代码的种类。能够指定为 exec, eval, single。
# flags -- 变量做用域,局部命名空间,若是被提供,能够是任何映射对象
# flags和dont_inherit是用来控制编译源码时的标志
compile_str = "for i in range(10): print(i)"
c_str = compile(compile_str, '', 'exec')
print("编译后执行结果是:", exec(c_str))
print("\n")


# 11. isinstance() --- 判断一个对象是不是一个已知类型,相似于type()
# isinstance()会认为子类是一种父类类型,考虑继承关系。
# type()不会认为子类是一种父类类型,不考虑继承关系
# isinstance(object, classinfo)
a11 = 11
print("%s 的类型为 %s" % (a11, isinstance(a11, int)))
print("%s 的类型为 %s" % (a11, isinstance(a11, (list, int, str))))
class A11(object):
    pass
class A12(A11):
    pass
print(isinstance(A11(), A11))
print(isinstance(A12(), A11))
print(type(A11()) == A11)
print(type(A12()) == A11)


# 12. issubclass(class, classinfo) --- 判断参数class是不是类型参数classinfo的子类
class Issub_A:
    pass
class Issub_B(Issub_A):
    pass
print("%s 是不是 %s的之类?%s" % (Issub_B, Issub_A, issubclass(Issub_B, Issub_A)))
print("\n")
# -------------------------
# callable() --- 检查一个对象是不是可嗲用的,若是返回True,object仍有可能调用失败;若是返回False,调用绝对失败
print("callable 1返回:", callable(0))
print("callable 2返回:", callable(pow))
print("\n")
# -------------------------
# locals() --- 以字典类型返回当前位置的所有局部变量
def return_local(x: object, y: object) -> object:
    z = 1
    print(locals())
all_result = return_local(2, 3)
print("返回当前位置的所有局部变量:", all_result)
print("\n")


# 13. super() --- 函数是用于调用父类(超类)的方法
# super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,可是若是使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题
# MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
class Super_A(object):
    def add(self,x):
        y = x + 1
        print(y)
class Super_B(Super_A):
    def add(self,x):
        super().add(x)
superb = Super_B()
superb.add(2)
print("\n")
# ------------------------------
# property() --- 在新式类中返回属性值
class Property_A(object):
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x

    def setx(self, value):
        self._x = value

    def delx(self):
        del self._x

    x = property(getx, setx, delx, "I'm the 'x' property.")
# -----------------------------------
# getattr() --- 返回一个对象属性值
class Getattr(object):
    bar = 1
g = Getattr()
print("获取属性值:", getattr(g, 'bar'))
print("\n")
# ------------------------------------
# delattr(object, name_of_atrr)
class Delattr(object):
    x = 1
    y = 2
    z = 3
d = Delattr()
print("d的属性:", d.x)
delattr(Delattr, 'x')
# print("d的属性:" % d.x)
print("\n")
# ------------------------------------
# setattr(object, name, value) -- 设置对象的属性值,该属性不必定是存在的
class Setattr(object):
    s1 = 1
s_1 = Setattr()
setattr(s_1, 's2', 5)
print("设置不存在属性的值:", s_1.s2)
print("\n")
# hasattr(object, name) --- 用于判断对象是否包含对应的属性
# object--对象;name--属性名字符串
class Hasattr(object):
    x = 10
    y = 100
    z = 1000
print("判断对象是否含有属性:", hasattr(Hasattr, 'x'))
print("判断对象是否含有属性:", hasattr(Hasattr, 'e'))
print("\n")


# 14. filter(function, iterable) --- 过滤序列中不符合条件的元素,返回由符合条件元素组成的新列表
# function --- 判断函数
# iterable --- 可迭代对象
import random
def func_filter(x):
    list_a = []
    for i1 in x:
        if (i1 % 2) == 0:
           list_a.append(i1)
    return list_a
filter_result = func_filter([1, 2, 3, 4])
print("过滤后的序列为:%s" % filter_result)


# 15. len() --- 返回对象(字符、列表、元组等)长度或项目个数
len_1 = "len"
len_2 = [1, 2, 3, 4]
len_3 = (1, 2, 3)
print("%s 的长度为:%s" % (len_1, len(len_1)))
print("%s 的长度为:%s" % (len_2, len(len_2)))
print("%s 的长度为:%s" % (len_3, len(len_3)))
print("\n")
# vars() --- 返回对象object的属性和属性值的字典对象。
class Vars_A(object):
    a = 1
print("vars()返回:", vars(Vars_A))
print("vars()返回:", vars(Vars_A()))
print("\n")
# -------------------------------------------------
# range(start, stop[, step])
range_result = range(10)
print("&&&&&&&&", range_result)
print("\n")
# -------------------------------------------------
# frozenset() --- 返回一个冻结集合,冻结后结合不能再添加或删除任何元素
frozenset_1 = frozenset(range(10))
print("frozenset1: %s" % frozenset_1)
frozenset_2 = frozenset("HELLO")
print("frozenset2: %s" % frozenset_2)
print("\n")
# --------------------------------------------------
# globals() --- 以字典类型返回当前位置的所有变量
globals_1 = 'test'
print("当前位置的全局变量:", globals())
print("\n")


# 16.memoryview --- 返回给定参数的内存查看对象(Momory view)。
# 所谓内存查看对象,是指对支持缓冲区协议的数据进行包装,在不须要复制对象基础上容许Python代码访问。
v = memoryview(bytearray('abc', 'utf-8'))
print(v[0])
print(v[1])
print(v[2])
print("\n")
# -------------------------
# round(x[, n]) --- 方法返回浮点数x的四舍五入值。
print(round(10.2565, 2))


# 17. help() --- 用于查看删除活模块的用途的详细说明
print(help('sys'))
print("\n")
# print(help('str'))
# --------------------------
# dir() --- 不带参数时,返回当前范围内的变量、方法和定义的类型列表;
# 带参数时,返回参数的属性、方法列表。若是参数包含方法__dir__(),该方法将被调用。
# 若是参数不包含__dir__(),该方法将最大限度地收集参数信息。
print("dir返回:", dir())
print("\n")
# id() --- 用于获取对象的内存地址
id_1 = '1'
id_2 = 1
id_3 = 4
print("%s 的内存id为:%s" % (id_1, id(id_1)))
print("%s 的内存id为:%s" % (id_2, id(id_2)))
print("%s 的内存id为:%s" % (id_3, id(id_3)))
print("\n")
复制代码

6、面向对象编程

  面向对象(Object Oriented)设计思想贯穿程序设计,面向对象编程(Object Oriented Programming)是针对大型软件设计提出的,它能使代码更好滴复用,使程序更加的灵活。对象 是一个抽象的概念,万事万物皆可对象。对象一般可划分为两个部分,静态部分动态部分 ;【静态部分】称之为 属性,【动态部分】称为 方法

  面向对象编程中,将函数和变量进一步封装成类,类才是程序的基本元素,它将数据和操做紧密链接,并保护数据不被外界意外改变。

1. 面向对象术语

面向对象中的相关术语整理以下:
(1)类(class):用来描述具备相同【属性】和【方法】的对象集合,定义了该集合中每一个对象所共有的属性和方法,其中对象被称为类的实例;
(2)实例:也称对象,经过类定义的初始化方法赋予具体的值;
(3)实例化:建立类的实例的过程;
(4)实例变量:定义在实例中的变量,只做用于当前实例;
(5)类变量:类变量是全部实例公有的变量。类变量定义在类中,但在方法体以外
(6)数据成员:类变量、实例变量、方法、类方法、静态方法和属性等的统称;
(7)方法:类中定义的函数;
(8)静态方法:不须要实例化就能够有类执行的方法;
(9)类方法:类方法是将类自己做为对象进行操做的方法;
(10)方法重写:从父类继承的方法不能知足子类的需求,可对父类的方法进行重写;
(11)继承:一个派生类继承父类的变量和方法;
(12)多态:根据对象类型的不一样以不一样的方式进行处理
复制代码
# (1)类
class OOPObject(object):
    # (5)类变量:定义在类中,方法以外的变量
    phone = 123456789
    address = "memory"

    # __init__方法的类在实例化的时候,会自动调用该方法,并传递对应的参数
    def __init__(self, name, age):
        # (4)实例变量,name 和 age就是实例变量
        self.name = name
        self.age = age

    # (7)实例方法
    def o_method(self):
        print("{0}:{1}".format(self.name, self.age))

    # (8)静态方法:不须要实例化就能够有类执行的方法
 @staticmethod
    def static_method():
        print("我是静态方法")

    # (9)类方法:类方法是将类自己做为对象进行操做的方法
    # 采用@classmethod装饰,至少传入一个cls(指类自己,相似于self)参数。
    # 执行类方法时,自动将调用该方法的类赋值给cls。
    # 使用类名.类方法的调用方式(也可使用实例名.类方法的方式调用)
 @classmethod
    def class_method(cls):
        print("我是类方法")


# (2)实例
# (3)实例化---这个过程
o1 = OOPObject("oj", 23)
# 实例方法的调用
o1.o_method()


# (6)数据成员:类变量、实例变量、方法、类方法、静态方法和属性等的统称

# (8)静态方法的调用
OOPObject.static_method()


# 类方法
OOPObject.class_method()
复制代码

2. 面向对象三特征

面向对象的三大特征:封装继承多态

2.1 封装

  封装是指将 数据具体操做 的代码放在某个对象内部。使这些代码的实现细节不被外界发现,外界只能经过接口访问该对象(外界也不能直接访问类的变量和方法),而不能经过任何形式修改对象内部的实现。【GitHub代码commits id:cc3bc98

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
""" @File : 62_OOPFeatures.py @Time : 2019/8/14 15:15 @Author : Crisimple @Github : https://crisimple.github.io/ @Contact : Crisimple@foxmail.com @License : (C)Copyright 2017-2019, Micro-Circle @Desc : None """

class ThisClass(object):
    class_name = 'This class'
    class_age = 12

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

    def print_class(self):
        print("{0}:{1}".format(self.name, self.age))


# 这就说明:外部不能直接调用类变量和类方法
# print(class_name) NameError: name 'class_name' is not defined
# print_class() NameError: name 'print_class' is not defined

# 使用:类名/实例名.变量/方法,来访问类的变量或方法
print(ThisClass.class_name)
ThisClass.class_name = 'Change name value'
print(ThisClass.class_name)
ThisClass.class_add_attribute = 'Test add attribute'
print(ThisClass.class_add_attribute)
tc = ThisClass('A', 23)
print(tc.print_class())
复制代码

2.2 继承

  继承实现了代码的复用,多个类公用的代码能够只在一个类中提供,其余类只需集成这个类便可。继承最大的好处就是 子类(新定义的类) 得到了 父类(被继承的类也可成为基类或超类) 的所有变量和方法同时,又能够根据需求进行修改和扩展。   继承又分为两类:实现继承(使用基类的属性和方法无需额外编码的能力)接口继承(仅使用属性和方法的名称,子类必须提供实现的能力,即子类重构父类方法)。【GitHub代码commits id:a7b3bee

2.2.1 构造方法的继承

继承构造方法的方式:

(1)经典继承的写法:父类名称.__init__(self, 参数1, 参数2)
    (2)新式类的写法:super(子类, self).__init__(self, 参数1,参数2)
    
    实例化对象b ---> b调用子类的构造方法__init__() ---> 子类的构造方法__init__()继承父类的构造方法__init__() ---> 调用父类的构造方法__init__()
复制代码
class FatherClass(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.country = 123

    def father_method(self):
        print('father is walking')


class BoyClass(FatherClass):
    # 先继承再重构,反着来子类就不能继承父类的属性了
    def __init__(self, name, age, sex):
        # 继承父类的构造方法
        # 经典继承
        # FatherClass.__init__(self, name, age)
        # 新式类继承
        super(BoyClass, self).__init__(name, age)
        # 定义子类自己的属性
        self.sex = sex

    def child_method(self):
        print('child is walking')


class GirlClass(FatherClass):
    pass


# 子类构造方法继承父类构造方法过程以下:
# 实例化对象b ---> b调用子类的构造方法__init__() ---> 子类的构造方法__init__()继承父类的构造方法__init__() ---> 调用父类的构造方法__init__()
b = BoyClass('Boy', 25, 'male')
print(b.name)
print(b.age)
print(b.sex)
print(b.country)
复制代码

2.2.2 子类对父类方法的重写

若是要对父类的方法进行修改,而又不影响其余继承父类的类,咱们能够再子类中重构该方法。

# 2.继承
class FatherClass(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.country = '中国'

    def father_method(self):
        print('father is walking')

    def talk(self):
        print("I'am father. %s" % self.name)


class BoyClass(FatherClass):
    # 先继承再重构,反着来子类就不能继承父类的属性了
    def __init__(self, name, age, sex):
        # 继承父类的构造方法
        # 经典继承
        # FatherClass.__init__(self, name, age)
        # 新式类继承
        super(BoyClass, self).__init__(name, age)
        # 定义子类自己的属性
        self.sex = sex
        print(self.name, self.age, self.country, self.sex)

    def child_method(self):
        print('child is walking...')

    def talk(self):
        print("I'am child. %s" % self.name)


class GirlClass(FatherClass):
    pass


# 2.1 构造方法继承
# 子类构造方法继承父类构造方法过程以下:
# 实例化对象b ---> b调用子类的构造方法__init__() ---> 子类的构造方法__init__()继承父类的构造方法__init__() ---> 调用父类的构造方法__init__()
b = BoyClass('Boy', 25, 'male')
print(b.name)
print(b.age)
print(b.sex)
print(b.country)
# 2.2 子类重写父类方法
f = FatherClass('A', 30)
f.talk()
b.talk()
复制代码

2.3 多态

  多态是指一类事物具备多种形态。Python的多态性是指在不考虑实例类型的状况使用实例,也就是说不一样类型的实例有相同的调用方法。【GitHub代码commits id:de62018

  使用多态的好处:

(1)增长了程序的灵活性:以不变应万变,不论对象变幻无穷,使用同一种形式去调用,如show_say(animal)
(2)增长了程序的可扩展性:经过继承Animal(下面代码例子)类建立了一个新的类,使用者无需更改本身的代码,仍是用show_say(animal)方法去调用。
复制代码
class Animal(object):       # 同一类事物:动物
    def say(self):
        print("I'm animal.")


class Dog(Animal):          # 动物的形态之一:狗
    def say(self):
        print("Wang wang~")


class Cat(Animal):          # 动物的形态之一:猫
    def say(self):
        print("Miao miao~")


class Cow(Animal):          # 动物的形态之一:牛
    def say(self):
        print("Mou mou~")


d = Dog()
ca = Cat()
co = Cow()
# d, ca, co 都是动物,都属于动物类,确定都有say_hi()方法,所以不用考虑他们具体是什么类型,直接使用便可
d.say()
ca.say()
co.say()
# 咱们能够统一一个接口来调用动物类的say_hi()方法
def show_say(animal):
    animal.say()


show_say(d)
show_say(ca)
show_say(co)
复制代码

3. 元类

  Python中一切皆对象,那么咱们用class关键字定义的类自己也是一个对象,负责产生该对象的类称之为元类。

  学习元类是为了控制类的产生过程,还能控制对象的产生过程。 【GitHub示例

3.1 渐入元类

  类对象能够用 class 关键字建立,类对象的类型是 type,也就是说能够经过 type(元类)来建立。

# 默认的元类type实例化出一个对象Foo,实例化的结果也是一个对象
class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def eat(self):
        print("%s is eating." % self.name)


f1 = Foo('mi', 9)


number = 12
dicts = {
    "name": "crisimple",
    "age": 23
}


print("number的ID是:", id(number))
print("dicts的ID是:", id(dicts))
print("number的type是:", type(number))
print("dicts的type是:", type(dicts))

print("Foo的ID是:", id(Foo))
print("Foo的type是:", type(Foo))      # Foo的type是: <class 'type'>
print("f1的ID是:", id(f1))
print("f1的type是:", type(f1))        # f1的type是: <class '__main__.Foo'>
# --------------------------------------
# instance ---[instance of]---> class ---[instance of]---> metaclass
# f1 ----------------> Foo --------------> type【type就是元类,元类本身也是对象】
复制代码

3.2 用元类建立类

Person = type("Person", (object, ), {"live": True, "name": 'crisimple'})
print(type(Person))
p1 = Person()
print(type(p1))
复制代码

=================【Python高级编程】===========