一等对象,x学习笔记2018

日期:2019-11-03编辑作者:明仕ms57编程

本文主要内容

一等对象

普通函数 & 高阶函数

可调用对象 & 自定义可调用类型

  函数内省

  函数注释

 

python高级——目录

文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级

 

前言:python3.x部分学习笔记,有意交流学习者可加wechat:YWNlODAyMzU5MTEzMTQ=。如果笔记内容有错,请指出来。

一等对象

'''
    在python中,"一等对象"指的是满足下述条件的程序实体:
    (1)在运行时创建
    (2)能赋值给变量或数据结构中的元素
    (3)能作为参数传给函数
    (4)能作为函数的返回结果

    整数、字符串和字典都是一等对象。在面向对象编程中,函数也是对象,并满足以上条件,所以函数也是一等对象,称为"一等函数"
'''


if __name__ == "__main__":
    # 函数的一等性质
    def foo(n):
        '''returns  n!'''
        return 1 if n < 2 else n * foo(n-1)

    print(foo(5))    # 120

    my_foo = foo
    print(my_foo)    # <function foo at 0x1010e3f28> 能赋值给变量
    print(list(map(my_foo, range(6))))   # [1, 1, 2, 6, 24, 120]   能赋值给函数

    def foo2():
        return foo

    my_foo2 = foo2()
    print(my_foo2(5))     # 120 可作为函数的返回结果

 


普通函数 & 高阶函数

'''
    我们一般将函数分为"普通函数"和"高阶函数",接受函数为参数的函数为高阶函数,其余为普通函数

    普通函数大家再熟悉不过,本文不讲,主要讲一下map、filter、reduce三个高阶函数
'''


if __name__ == "__main__":
    # map第一个参数接受一个函数,并将这个函数作用于后面可迭代对象的每一个元素中
    l = map(lambda x : x ** 2, range(11))   # 返回的是生成器类型
    print(list(l))     # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    w = map(str.upper, 'asfafasfasfaf')
    print(list(w))     # ['A', 'S', 'F', 'A', 'F', 'A', 'S', 'F', 'A', 'S', 'F', 'A', 'F']

    # filter第一个参数也接受函数,并返回所有满足该函数的元素
    l = filter(lambda n: n % 2, range(10))   # 返回n % 2为真的数,就是奇数
    l2 = filter(lambda n: n % 2 ==0, range(10))  # 返回偶数
    print(list(l))                           # [1, 3, 5, 7, 9]
    print(list(l2))                          # [0, 2, 4, 6, 8]

    # reduce 从python3开始,reduce放在functools中
    # reduce将某个操作连续应用到序列元素上,即其会将前一步的结果继续应用到下一个元素上
    from functools import reduce
    s = reduce(lambda x,y: x + y, range(101))
    print(s)       # 5050 对1到100求和

 

图片 1

 可调用对象 & 自定义可调用类型

'''
    我们在使用函数或者实例化对象的时候会用到括号(即()),这个括号实际上是调用运算符,python里面有7中可调用对象:

    1、用户定义的函数
        def和lambda创建
    2、内置函数
        使用C语言实现的函数,如len或time.strftime
    3、内置方法
        使用C语言实现的方法,如dict.get
    4、方法
        在类的定义体中定义的函数
    5、类
        调用类时其实首先运行的是__new__方法,然后运行__init__方法。这里很有意思,自定义类中其实没有重写__new__方法,
        而是调用的超类的__new__方法,如果查看源代码的实现逻辑,相信你会有新的发现,这里不做讨论。
    6、类的实例
        如果类定义了__call__方法,那么它的实例可以作为函数调用
    7、生长器函数
        使用yield关键字的函数或方法。
'''


if __name__ == "__main__":
    # 创建一个自定义可调用类
    class Foo():
        def __init__(self):
            self.name = "Foo"
        def __call__(self, *args, **kwargs):
            print("调用__call__")

    Foo()()     # 输出:调用__call__

    # 以上使用 Foo()() 这种写法看上去很有意思。首先,Foo()会创建一个Foo实例,调用__init__构造方法,; 然后使用实例(),此时
    # 调用__call__方法

 

python笔记目录导图

函数内省

'''
    函数内省我们通过例子来看
'''


if __name__ == "__main__":
    # 先创建一个函数
    def foo(n):
        ''':returns n!'''
        return 1 if n<2 else n*foo(n-1)

    print(foo.__doc__)   # :returns n!   __doc__里面存储了注释内容

    # 看看这个函数中有多少属性
    print(dir(foo))
    '''
        ['__annotations__', '__call__', '__class__', '__closure__', '__code__', 
        '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', 
        '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', 
        '__hash__', '__init__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', 
        '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', 
        '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    '''

    # 下表对一些属性做了说明
名称 类型 说明
__annotations__ dict 参数和返回值的注解
__call__ method-wrapper 实现()运算符
__closure__ tuple 函数闭包
__code__ code 编译成字节码的函数元数据和函数定义体
__defaults__ tuple 形式参数的默认值
__get__ method-wrapper 实现只读描述符协议
__globals__ dict 函数所在模块中的全局变量
__kwdefaults__ dict 仅限关键字形式参数的默认值
__name__ str 函数名称
__qualname__ str 函数的限定名称

 

对数据类型的操作

  1. 可变数据类型:列表,集合,字典
    列表:
li=['a','b']
增:
li.insert(2,'c')  #在序号2位置上插入'c'
li.append('d')  #在列表末尾添加'd'
li.extend(li2)  #在列表li后面添加li2

删:
li.remove('c')
del li[2]
li.pop(3)

改:
li[2]='c'
li[1:-1:1]='ha'

查:
li.index('c') 

排序:
sort(key=lambda x:x[2],reverse=True)

集合:

#去重
#关系测试
s1={1,2,3,4,5},s2=set([4,5,6,7,8])
s3=s1&s2  #求交集
s4=s1|s2  #求并集

字典:

a_dict={'name':'alex','age':12,'sex':'male'}
a_dict.get('name','wrong')  #找键名对应的值,找不到就返回第二参数
a_dict.setdefault('name','lema')  #查找该键,找不到则插入该键值对
a_dict.update(dict2)  #将dict2添加到a_dict中
  1. 不可变数据类型:元组,字符串
    元组:tuple1=(1,2,3,4,5)
    字符串:
str1='abcdef',str2="a|b|c|d"
print(str1.capitalize(),str1.upper(),str1.lower())  #首字母大写,全部大写,全部小写
print(str1.find(str2,2,5))  #在str1中从序号2位置开始找str2,直到序号5的位置
print(str1.center(20,'*'))  #在字符串两边各添加20个'*'
print(str1.startswith('ab')+','+str1.endswith('ef'))  #返回True或False
print('-'.join(['2018','1','1']))
print(str2.split("|",3))  #返回一个列表
print(str1.replace('a','A',1))  #把str1中的第1个a替换成A
print(str1.strip())  #把str1两边的空白字符去掉

函数注释

'''
    函数注解很简单,用下面例子简单讲解即可明了
'''


if __name__ == "__main__":
    def foo(num: int, step: 'int 间隔(大于0小于num)'=1) -> int:
        ''':returns 求num的阶乘,可以设置步长'''     # 这里的注释存储在__doc__中
        return num if num <= step else num * foo(num-step,step)

    print(foo(5))  # 120   (5*4*3*2*1)
    print(foo(5, 2))  # 15 (5*3)

    # 函数声明中的各个参数可以在冒号(:)之后增加注释,该注释可以直接写参数类型,也可以写字符串
    # -> 符号后面是对函数返回值进行注解

    # 这些注释内容存储在属性 __annotations__中
    print(foo.__annotations__)  # {'step': 'int 间隔(大于0小于num)', 'num': <class 'int'>, 'return': <class 'int'>}

    # 这样注释后,在使用pycharm时会出现自动提示

 

 

 

函数

  1. 高阶函数
def func(x,y,f):
    print(f)
    print(type(f))
    return f(x)+f(y)
result=func(-3,-2,abs)
print(result)
  1. 装饰器
    不修改被装饰函数的源代码
    不修改被装饰函数的调用方式
def auth(func):
    def wrapper(*args,**kwargs):
                username=input("username:").strip()
                password=input("password:").strip()
                if "lema"==username and "qwert123"==password :
                    res=func(*args,**kwargs)
                else :
                    print("wrong")
                return res
    return wrapper

@auth
def index(x,y,f):
    print(f(x)+f(y))
    print("welcome to myblog")
    return "ok"
print(index(-3,-4,abs))
  1. 参数
    关键字参数
    位置参数
    可变参数
  2. 特殊函数

python高级系列文章目录

python高级——目录

 

面向对象

class People(object):
    name="yin"  #类变量
    def __init__(self,name,age=6):  #构造函数
        self.name=name  #实例变量self.name
    def __del__(self):  #析构函数,当实例对象被垃圾回收时执行该函数
        print("end")
    def sleep(self):
        print("%s:hello,world"%self.name)
d1=People("d1",age=5)
del d1,People
  1. 继承
    重写父类方法
    重构父类方法
class Man(People):
    #第一种重构方式
    def sleep(self):
        People.sleep(self)
        print("chonggou")
    #第二种重构方式,建议使用第二种
    def sleep(self):
          super(Man,self).sleep()
          print("chonggou")

多继承父类方法查询策略:广度优先

class A(object):
    def func(self):
        print("A")
class B(A):
    # def func(self):
    #     print("B")
    pass
class C(A):
    def func(self):
        print("C")
    def f(self):
        print("1000")
class D(B,C):
    def func(self):
        super(D,self).func()
        super(D,self).f()
        print("D")
d=D()
d.func()
  1. 多态:一种接口,多种实现
  2. 方法
    静态方法@staticmethod:名义上归类管理,实际上访问不了类和实例中的任何属性
    类方法@classmethod:只能访问类变量,不能访问实例变量
    属性方法@property:把一个方法转换成静态属性
class Person(object):
    def __init__(self,first_name,last_name):
        self.first_name=first_name
        self.last_name=last_name
    @property
    def full_name(self):
        return "%s %s"%(self.first_name,self.last_name)
    @full_name.setter
    def first_namex(self,first_name):
        self.first_name=first_name
p1=Person("Mike","Driscoll")
print(p1.full_name)
p1.first_namex="lema"
print(p1.full_name)

伪私有方法:

#以双下划线开头的类方法名,在类实例化以后会自动被概念,在其名字前加 _类名. 
#因为名字被改了,所以自然无法用双下划开头的名字被访问,从而达到不可进入的目的
class Person(object):
    def __func(self):
       pass
p1=Person()
p1._Person__func()

类名.__doc__:返回该类的注释说明
__module__
__class__
__call__
def __str__(self): pass

class Dog(object):
    def __init__(self):
        print("执行init")
    def __str__(self):
        return "执行__str__"
d1=Dog()
print(d1)
  1. 反射:hasattr,getattr,setattr,delattr
def bulk():
    print("往实例对象中添加一个函数")
class Dog(object):
    def __init__(self,name):
        self.name=name
    def eat(self,food):
        print(self.name+":"+food)
d1=Dog("lema")
choice=input(">>:").strip()
#反射的是函数
if hasattr(d1,choice):  #hasattr判断一个对象里是否有字符串对应的方法属性
    func=getattr(d1,choice)  
    func("rice")
else:
    setattr(d1,choice,bulk)
d1.talk()  #假设输入的是talk
#反射的是属性
print(d1.name)
if hasattr(d1,choice):
    attr=getattr(d1,choice)
    setattr(d1,choice,"ronghua")
else:
    setattr(d1,choice,22)
print(d1.name)  #假设输入的是name
print(d1.age)  #假设输入的是age

模块

  1. 内置模块(标准库)
    sys
import sys
print("脚本名称:",sys.argv[0])
for i in sys.argv[1:]:
    print("参数",i)
#退出程序,正常退出则返回0
sys.exit(0)
#标准输入
for line in sys.stdin:
    print("abc",line)

time/datatime

import time,datatime
time.sleep(0.5)
today=datetime.date.today()
print(str(today.year)+'-'+str(today.month)+'-'+str(today.day))
now=datetime.datetime.now()  #now.minute,now.day.now.second...

random

import random
#随机生成四位验证码
checkcode=""
for i in range(4):
    checkcode+=random.choice("1234567890")
print(checkcode)
print(random.randint(11,13))  #生成11或12或13
print(random.randrange(2,10,2))  #生成2,4,6,8
#打乱元素
li=[1,2,3,4,5,6,7,8]
random.shuffle(li)
print(li)

hashlib

import hashlib
m1=hashlib.md5()
m1.update(b"admin")
m1.update(b"123")
print(m1.hexdigest())
m2=hashlib.md5()
m2.update("admin123".encode())
print(m2.hexdigest())

re

import re
# re.match()从字符串初始位置开始查找,若初始位置开始匹配错误,返回None
print(re.match("chend+","rchen321"))
print(re.match("chend+","chen321").group())
# re.search()从字符串全局开始查找,只匹配第一个找到的
print(re.search("chend+","rchen321").group())
# 分离字符串,返回["abc","de","f"]
print(re.split("[0-9]+","abc12de34f"))
# 替换匹配到的字符,返回"abc11de14f"
print(re.sub("[0-9]","1","abc52de34f",count=3))
# 列表形式返回所有查找到的结果
print(re.findall("chend+","chen321 chen14"))

os

import os,os.path
# os.popen()返回一个file对象
cmd_res=os.popen("dir").read()
print(cmd_res)
# 判断文件或目录是否存在
print(os.path.exists("test.py"))
print(os.path.exists("D:softwareAnaconda"))
print(os.path.isfile("test.py"))
print(os.path.isdir("D:softwareAnaconda"))
# 路径拼接
print(os.path.join('/home/aa','/home/aa/','/home/aa/bb/c'))
# 将路径与扩展名分离
print(os.path.splitext("/home/haha.py"))  # 返回一个二元组
# 获取文件的大小
print(os.path.getsize("test.py"))  
# 获取相关文件的系统状态信息,st_atime,st_mtime,st_ctime...
print(os.stat("test.py").st_size)
# 将相对路径转换成绝对路径
print(os.path.abspath(__file__))
  1. 第三方库(开源模块)
  2. 自定义模块
  3. 导入模块与导入包:
    导入包的本质就是解释包下面的__init__.py文件
import module1_name,module2_name # 解释包下面的__init__.py文件
from module_name import *  #不推荐使用
from random import randint as ri # 解释包下面的randint.py文件
from module_name import func1,func2

#动态加载模块
mod1=__import__("baobao.test")
print(mod1)
mod1.test.func()
#官方建议使用下面的用法
import importlib
mod2=importlib.import_module("baobao.test")
print(mod2)
mod2.func()

文件操作

  1. 文件读取&写入
with open("test.txt","r+",encoding="utf-8") as f:
    f.write("hello456n")
    f.writelines(["hello", "world", "n"])
    #逐行读取文本内容
    for line in f:
        print(line)
    #一次性读取当前光标后的10个字符
    print(f.read(10))
    print(f.tell())  #获得当前文件的光标
    f.seek(0)  #将光标移动到最开始的地方
  1. 文件打开的模式
    "r":只读模式
    "w":创建或覆盖模式
    "a":追加模式
    "r+":读写模式

其它特性:

  1. 生成器
    把列表生成式的[]改为()
[i*2 for i in range(10000000)]  #列表生成式,[func(i) for i in range(10)]
(i*2 for i in range(1000000))  #生成器

含yield的函数

  1. 迭代
    可迭代对象:可以通过for循环来遍历的对象称为可迭代对象,比如str,dict,list,tuple,set,生成器
    迭代器:可以被next()函数调用并返回下一个值的对象称为迭代器,把可迭代对象变成iterator可以使用iter()函数
  2. 垃圾自动回收机制
    del:函数名,实例名,变量名,类名
  3. 异常处理
data={}
li=[1,2]
try:
    open("test.txt",r)
    data['name']
    li[3]
except KeyError as e:
    print("没有这个键",e)
except IndexError as e:
    print("列表操作错误",e)
except Exception as e:
    print("未知错误")
else:
    print("一切正常")
finally:
    print("不管有无错误,照常执行")

#自定义异常
class AlexException(Exception):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        #print(self.msg)
        return self.msg
try:
    raise AlexException("我的异常")
except AlexException as e:
    print(e)

#断言
num=13
assert type(num) is str
print("right")

软件目录结构规范

Foo
    bin                  # 存放一些项目的可执行文件
        一键启动.py
    core                 # 存放项目的所有源代码
        tests            # 存放单元测试代码
            __init__.py
            test_main.py
        __init__.py
        main.py
    docs                  # 存放一些文档
        conf.py
        abc.rst
    setup.py              # 安装,部署,打包的脚本
    requirements.txt      # 存放软件依赖的外部python包列表
    README                #项目说明文件
        1.软件定位,软件的基本功能
        2.运行代码的方法,安装环境,启动命令等
        3.简要的使用说明
        4.代码目录结构说明
        5.常见问题说明

多线程&多进程&协程

import threading,time
def run(n):
    print("task:",n)
    time.sleep(2)
    print(threading.current_thread()) # 返回当前线程对象
    print(threading.active_count()) # 返回当前存活线程数量
    print(threading.main_thread()) # 返回主线程对象
start_time=time.time()
t_total=[]
for i in range(50):
    t2=threading.Thread(target=run,args=("t%s"%i,))
    t2.setDaemon(True) # 把当前线程设置为守护线程
    t2.start() # 主线程启动子线程
    t_total.append(t2)
# for t in t_total:
#     t.join() # 一个线程等到另一个线程执行结束后再执行下面的代码
end_time=time.time()
print(threading.current_thread())
print(end_time-start_time)

# 线程交互
import time,threading
event=threading.Event()
def lighter():
    count=0
    event.set() # 设置标志位
    while True:
        if count>5 and count<=10: # 变红灯
            event.clear() # 把标志位清空
            print("红灯停")
        elif count>10:
            event.set() # 变绿灯
            count=0
        else:
            print("绿灯行")
        time.sleep(1)
        count+=1
light=threading.Thread(target=lighter,)
light.start()
def car(name):
    while True:
        if event.is_set():
            print("     %s正在行驶"%name)
            time.sleep(1)
        else:
            print("     %s正在等待"%name)
            time.sleep(1)
            event.wait()
car1=threading.Thread(target=car,args=("奔驰",))
car2=threading.Thread(target=car,args=("兰博基尼",))
car1.start()
car2.start()

# queue队列
# queue.Queue(maxsize=0) 顺序先入先出
# queue.LifoQueue(maxsize=0) 顺序后入先出,last in first out
# queue.PriorityQueue(maxsize=0) 存储数据时可设置优先级
import queue
try:
    q=queue.Queue(maxsize=3)
    q.put("d1")
    q.put("d2")
    q.put("d3")
    q.put("d4",block=False)
    print(q.qsize()) # 返回队列长度
    print(q.get())
    print(q.get_nowait())
    print(q.get_nowait())
    print(q.get(block=False)) # 非阻塞
    print(q.get(timeout=3))
    print(q.get_nowait())
except queue.Empty as e:
    print("队列为空")
except queue.Full as e:
    print("队列满了")

q2=queue.PriorityQueue()
q2.put((-2,"lema"))
q2.put((34,"asd"))
q2.put((11,"qwe"))
print(q2.get())
print(q2.get())
print(q2.get())

本文由明仕ms577发布于明仕ms57编程,转载请注明出处:一等对象,x学习笔记2018

关键词:

文本和字节序列

文本和字节序列。正文首要内容 字符 文本和字节序列。字节 文本和字节序列。文本和字节序列。结构体和内部存款...

详细>>

移动开发中Fiddler的那些事儿,代理插件

本插件作用是把某些请求代理到指定的IP(端号)或文件,设置简便。   源码地址: 当我以前在调PC端网页的时候,...

详细>>

如何在Swift3中获取Json包的内容

我想在这个帖子里面总结两个问题:一个是通过ReST获取Json的语句,这个比较简单 另一个是如何将Json包一层一层转存...

详细>>

Ubuntu下将现有的文件打包成deb包

Ubuntu下将现有的文件打包成deb包。转自:   Ubuntu下将现有的文件打包成deb包。deb是DebianLinux的软件包格式。一般来说...

详细>>