python高级进阶

           对于python的学习已经有一段时间了,今天就其日常使用进行一个简单总结:

0、常见的内置函数

  • dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。 如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息
  • cmp(x,y) 函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。
  • all() 函数用于判断给定的可迭代参数 iterable 中的所有元素是否不为 0、''、False 或者 iterable 为空,如果是返回 True, 否则返回 False。(iterable为空也返回true)
  • any() 函数用于判断给定的可迭代参数 iterable 是否全部为空对象,如果都为空、0、false,则返回 False,如果不都为空、0、false,则返回 True。

1、enumerate

      enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

>>>seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))       # 下标从 1 开始
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

####for循环
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
...     print i, element
... 
0 one
1 two
2 three

2、zip

zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b)     # 打包为元组的列表
[(1, 4), (2, 5), (3, 6)]
>>> zip(a,c)              # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
>>> zip(*zipped)          # 与 zip 相反,*zipped 可理解为解压,返回二维矩阵式
[(1, 2, 3), (4, 5, 6)]

3、map

map() 会根据提供的函数对指定序列做映射。

第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。

形式为:map(function, iterable, ...),实例如下:

>>>def square(x) :            # 计算平方数
...     return x ** 2
... 
>>> map(square, [1,2,3,4,5])   # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> map(lambda x: x ** 2, [1, 2, 3, 4, 5])  # 使用 lambda 匿名函数
[1, 4, 9, 16, 25]
 
# 提供了两个列表,对相同位置的列表数据进行相加
>>> map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[3, 7, 11, 15, 19]

4、表达式

  • 三元表达式
if x >0:
    y=math.log(x)
else:
    y=float('nan')

####等价于
y=math.log(x) if x>0 else float('nan')
  • 列表生成式
l1=[]
for i in range(100):
    if i%2 ==0:
        l1.append(i)

#####is equal to
l1=[i for i in range(100) if i%2==0]
  • 字典表达式
keys=['name','age','sex']
values=['egon','18','male']
d={k:v for k,v in zip(keys,values)}
  • 生成器表达:小括号()
g=(i for i in range(10))  ##定义为迭代器对象不执行代码,知道next才执行一次代码
print(next(g))

常见的还有匿名表达式lambda,具体使用如下

f=lambda x:x**2 if x<10 else x
f(2)

###结合其他内置函数来巧用匿名函数,比如根据value值来返回key值
max(dic,key=lambda i:dic[i]) ##等价于max(dic,key=dic.get),等价于max(zip(dic.values(),dic.keys())[1]

5、迭代器

迭代器是一个可以记住遍历的位置的对象。

迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。

迭代器有两个基本的方法:iter() 和 next()

字符串,列表或元组对象都可用于创建迭代器:

>>> list=[1,2,3,4]
>>> it = iter(list)    # 创建迭代器对象
>>> print (next(it))   # 输出迭代器的下一个元素
1
>>> print (next(it))
2

创建一个迭代器

可迭代对象:内部实现了__iter__()或者__getitem__()方法即可成为一个可迭代对象,可以通过for循环完成遍历。

把一个类作为一个迭代器使用需要在类中实现两个方法 __iter__() 与 __next__() 。

如果你已经了解的面向对象编程,就知道类都有一个构造函数,Python 的构造函数为 __init__(), 它会在对象初始化的时候执行。

更多内容查阅:Python3 面向对象

__iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。

__next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。

####斐波那契数列
class Fibonacci:
  def __init__(self, count):
    self.count = count

  def __iter__(self):
    self.i = 0
    self.a, self.b = 0, 1
    return self

  def __next__(self):
  if self.i < self.count:
    self.i += 1
    a_old = self.a
    self.a, self.b = self.b, self.a + self.b
    return a_old
  else:
    raise StopIteration    ####StopIteration 异常用于标识迭代的完成,防止出现无限循环的情 
                           ####况,在 __next__() 方法中我们可以设置在完成指定循环次数后触发 
                           ####StopIteration 异常来结束迭代。

for i in Fibonacci(10):
  print(i, end=" ")

6、生成器

在 Python 中,使用了 yield关键字 的函数被称为生成器(generator)函数。

跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个特殊的迭代器。

在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

调用一个生成器函数,返回的是一个迭代器对象。

import sys
 
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
 
while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

生成器中yield关键字的作用:

  • 程序每次在代码中遇到yield关键字后,会返回结果
  • 保存当前函数的运行状态,等待下一次调用,下次调用时从上一次返回yield的语句处开始执行后面的语句。
def demo():
    print("hello")
    yield 5
    print("world")

def demo1():
    print("hello1")
    return 5

c=demo()  ###没有执行生成器函数
a=demo1()  ##普通函数,在调用时直接执行
print(next(c))
#print(next(c))  ###由于生成器运行到print("world")后,会报stopIteration错误,可以采用下面方法俩解决

for i in c:
    print(i)

send方法的作用:

  • 像next方法一样去调用生成器(调用生成器的方法有两种:next方法(for循环底层也是这种),send方法)
  • send方法在调用生成器时,可以同时给生成器传递数据到生成器内部。
def demo():
    print("hello")
    t=yield 5 ###yield右半部分是返回给调用方的值,左边是通过send方法传入到生成器内部来赋值的
    print("world")
    print(t)

c=demo() ##此时并没有执行生成器函数
#print(next(c))  ###预激活生成器1
print(c.send(None)) ##预激活生成器2
c.send('test') ##send方法调用生成器并且把test字符串传入到生成器内部

预激活生成器的两种方法:

  • 直接调用next方法来激活生成器
  • 调用send(None)方法来激活生成器

 

7、修饰器/修饰器

      装饰器的作用就是为已经存在的函数或对象添加额外的功能,其本质也是函数。函数的作用就是减少重复性的操作,降低代码的冗余,而在某种程度上,修饰器就是Python里为了解决函数重复调用问题而开发的一种语法操作。

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

在介绍修饰器之前,先介绍一个闭包的概念:

# print_msg是外围函数
def print_msg():
    msg = "I'm closure"

    # printer是嵌套函数
    def printer():
        print(msg)
    return printer

# 这里获得的就是一个闭包  
closure = print_msg()
# 输出 I'm closure
closure()

下面就一个简单的例子来简单介绍下修饰器:

import time

def funa(fun):
    def test():  ###如果加上*args,**kwags则表示参数不定,可选择使用
        t1=time.time()
        res=fun()
        t2=time.time()
        print(t2-t1)
        return res
    return test

@funa
def funb():    ###其实等价于funb=funa(funb)
    count=0
    for i in range(1000):
         count+=i
    return count

print(funb())

常见的几种装饰器类型:

  • 普通装饰器(如上)
  • 被装饰器函数带参数(内包函数带上形参*args,**kwsgs)
  • 装饰器本身带参数
  • 被装饰函数带返回值
##被装饰函数带有参数或不带参数
def deco(func):
    def inner(*args,**kwargs):
        ###包含所有要附加的功能
        func(*args,**kwargs)
    return inner

##装饰器本身带参数
def deco1(param): ##param是装饰器本身的参数
    def outer(func): ##以被装饰的函数名作为参数
        def inner(*args,**kwargs):
            ###包含所有附加的功能
            func(*args,**kwargs)
        return inner
    return outer

##被装饰器带返回值
def deco2(param):  ##param是装饰器本身的参数
    def outer(func): ##以被装饰的函数名作为参数
        def inner(*args,**kwargs):
            ###包含所有附加的功能
            result=func(*args,**kwargs)
            return result
        return inner
    return outer


@dec
@deco1("haha") 
@deco2("haha")
def func(par):
    print("the parameters include",par)
    return par
    
func(1)

可以发现装饰器简化了函数的调用,就像装修一样,当房子装修好了,当说到房子时就自动带上了房间的装饰。@语法只是将函数传入装饰器函数,@functools.wraps(func),这是python提供的装饰器。它能把原函数的元信息拷贝到装饰器里面的 func 函数中。函数的元信息包括docstring、name、参数列表等等。可以尝试去除@functools.wraps(func),你会发现test.__name__的输出变成了wrapper。而带参数的装饰器使用如下,可参考https://blog.csdn.net/dengchengtiantian/article/details/90044345

https://blog.csdn.net/luoz_java/article/details/90339876

import functools

def log_with_param(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            print('call %s():' % func.__name__)
            print('args = {}'.format(*args))
            print('log_param = {}'.format(text))
            return func(*args, **kwargs)

        return wrapper

    return decorator
    
@log_with_param("param")
def test_with_param(p):
    print(test_with_param.__name__)


# 传入装饰器的参数,并接收返回的decorator函数
decorator = log_with_param("param")
# 传入test_with_param函数
wrapper = decorator(test_with_param)
# 调用装饰器函数
wrapper("I'm a param")


###与上面的形式等同
call test_with_param():
args = I'm a param
log_param = param
test_with_param

此外Python还有3个内置的装饰器,都是针对类而言的,具体是@property 修饰,就是将方法,变成一个属性来使用;@classmethod 修饰类的方式与@staticmethod 修饰类的方式都可以将类的方法通过类名直接访问。

class Student(object):
    def __init__(self):
        self.__number = 2014020222

    # 定义一个函数,用来获取私有属性值的函数
    def get_number(self):
        return self.__number

    # 定义一个函数,用来设置私有属性值
    def set_number(self, value):
        # 设置私有属性值
        self.__number = value

    # @property 装饰一个对象函数,在这个对象函数中,返回__number的值
    # @property会将age函数声明为一个getter函数,getter函数一般用来获取值的操作,所以在函数中一般都会返回一个执行结果
    @property
    def number(self):
        # 返回私有属性值
        return self.__number

    # @number.setter  装饰一个对象函数,用来设置私有属性值
    @number.setter
    def number(self, value):
        # 设置私有属性值
        print("调用setter")
        self.__number = value

    # @number.setter  装饰一个对象函数,用来获取私有属性值
    @number.getter
    def number(self):
        print("调用getter")
        return self.__number

    # @number.deleter  装饰一个对象函数,用来删除私有属性值
    @number.deleter
    def number(self):
        print("调用deleter")
        del self.__number

# 在类声明的外部。获取私有属性的值
s = Student()
# number = s.get_number()
# print(number)
# s.set_number(2015020222)

# 通过调用@property装饰的number函数获取私有属性值
print(s.number)
# 通过调用@number.setter装饰的number函数,设置私有属性值
s.number = 2018020222
print(s.number)
del s.number

'''
结果为:
调用getter
2014020222
调用setter
调用getter
2018020222
调用deleter
'''

 

8、反射机制

     这里介绍python的四个内置函数,以一个简单的示例来说明

###新建一个example.py文件,内容如下
flag = 1  # 此变量在介绍反射机制时会用到
  
def my_sum(a, b):
  
  return a + b
  
def my_sub(a, b):
  
  return a - b
  •  getattr()

这个函数是Python自省的核心函数,它不仅可以用于在模块中查找获取相应的方法和变量,也可以在一个对象中查找和获取相应的方法和变量,这里就不具体介绍了。

imp = input("请输入你需要导入的模块名称:")  ##动态导包,输入example
count = __import__(imp)
  
func = input("请输入你需要使用的函数名:")   ###获得包内my_sum函数
  
f = getattr(count, func, None)
  
# 加法
sum = f(2, 3)
print(sum)
  • hasattr(object, name)

判断模块(或对象object)是否包含名为name的方法或变量(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的)

1

2

3

4

imp = input("请输入你想导入的模块名称:")

count = __import__('imp, fromlist=True)

  

print(hasattr(count, "my_sum"))  # 判断模块count中是否存在my_sum方法,存在返回True

  • setattr(object, name, value)

这是相对应的getattr()。参数是一个对象,一个字符串和一个任意值。字符串name可以是对象(object)中一个现有的属性或一个新的属性,这个函数将值(value)赋给属性(name)的。使用示例,setattr(x, y, v)相当于x.y = v。

1

2

3

4

5

6

imp = input("请输入你想导入的模块名称:")

count = __import__(imp, fromlist=True)

  

setattr(count, "flag", 0# 即使example模块中没有flag变量,此处也成立,没有的话相当于给模块中新增一个变量flag

  

print(count.flag)  # 打印出flag的值为0

  • delattr(object, name)

与setattr()相关的一组函数。参数是由一个对象(记住!python中一切皆是对象)和一个字符串(name)组成的。name参数必须是对象属性名之一。该函数删除该对象的一个由字符串(name)指定的属性。delattr(x, y)=del x.y.

1

2

3

4

5

6

imp = input("请输入你想导入的模块名称:")

count = __import__(imp, fromlist=True)

  

delattr(count, "flag")

  

print(count.flag)  # 此处再打印flag的值将会报错,因为上一步已经将flag属性删除了

需要注意的是getattr,hasattr,setattr,delattr函数对模块的修改都在内存中进行,并不会影响文件中真实内容。自省和反射是两个比较专业化的术语,首先自省是获取对象的能力,而反射是操纵对象的能力。Python中使用delattr()和setattr()实现反射,而其他方法则属于自省。反射和自省常常组合使用!


补:

常见的进制转化借助Python内置函数实现比较简单

import os,sys

# global definition
# base = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F]
base = [str(x) for x in range(10)] + [ chr(x) for x in range(ord('A'),ord('A')+6)]

# bin2dec
# 二进制 to 十进制: int(str,n=10) 
def bin2dec(string_num):
    return str(int(string_num, 2))

# hex2dec
# 十六进制 to 十进制
def hex2dec(string_num):
    return str(int(string_num.upper(), 16))

# dec2bin
# 十进制 to 二进制: bin() 
def dec2bin(string_num):
    num = int(string_num)
    mid = []
    while True:
        if num == 0: break
        num,rem = divmod(num, 2)
        mid.append(base[rem])

    return ''.join([str(x) for x in mid[::-1]])

# dec2hex
# 十进制 to 八进制: oct() 
# 十进制 to 十六进制: hex() 
def dec2hex(string_num):
    num = int(string_num)
    mid = []
    while True:
        if num == 0: break
        num,rem = divmod(num, 16)
        mid.append(base[rem])

    return ''.join([str(x) for x in mid[::-1]])

# hex2tobin
# 十六进制 to 二进制: bin(int(str,16)) 
def hex2bin(string_num):
    return dec2bin(hex2dec(string_num.upper()))

# bin2hex
# 二进制 to 十六进制: hex(int(str,2)) 
def bin2hex(string_num):
    return dec2hex(bin2dec(string_num))

未完继续!

 

参考链接:

1、https://www.runoob.com/python/python-built-in-functions.html(Python 内置函数)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值