python既支持函数编程,也支持面向对象编程,很多情况下,二者都能完成某个任务,java只支持面向对象。
功能居多,面向用户,如每个请求对应一个功能,功能驱动,业务功能多:函数
封装多,开源组件,精炼,提取公共部分,等:写面向对象。如Django框架,drf,全是类, 封装成一个组件时,重用性高,使用起来更简洁。
python函数特点:

  • 函数作用域:
    python中以一个函数为一个作用域,不是以冒号为作用域的,和JavaScript没有let关键字前一样。java以{}为作用域,如果在{}声明了一个变量,只能在{}这个作用域使用该变量
    全局也是个作用域,可以看成一个大函数,

  • pass
    流程占位

  • 函数的参数
    *args 容纳传过来的参数,动态插入,传多少都行
    **kwargs
    如果函数中某个参数为可变类型,没有执行前,编译过程中,不仅生成了一个函数内存,还生成了了一个另外一个空间,存放默认的可变数据类型
    例:

def f(n, n2=[]):  # 如果函数中某个参数为可变类型,没有执行前,编译过程中,不仅生成了一个函数内存,还生成了了一个n2=[]的空间,
    n2.append(n)
    return n2



l2 = f(666)   # 如果没有传n2,默认使用空列表,内存中的内容为[666,]
print(l2)
print(id(l2))


l1 = f(1, [2, 3])  # 由于传了新值,开辟了新的空间
print(l1)


l3 = f(2)  # 没有传第二个参数,还是用默认的空间中的值
print(l3)
print(id(l3))

运行结果

[666]
2282968690504
[2, 3, 1]
[666, 2]
2282968690504

函数补充

  • 列表生成式
data = [lambda :i for i in range(10)]

ret = data[5]()

print(ret)

运行结果

9

由于i这个变量在内存空间中一直被重新赋值,最终为9,所以执行时都是9

  • 装饰器
    场景
    flask框架路由
    django的csrf
    django的缓存
    django的auth认证组件
    基本装饰器:
import functools


def wapper(func):
    @functools.wraps(func)  # 加了这个装饰器,函数的原信息保留下来了
    def inner(*args, **kwargs):
        return func(*args, **kwargs)
    return inner


def f1():
    pass


print(f1, f1.__name__)


@wapper
def f1():  # 执行时:wapper(f1)()
    pass


print(f1, f1.__name__)

运行结果:

<function f1 at 0x000001CF622BEC80> f1
<function f1 at 0x000001CF61BD41E0> f1  实际是inner地址

例1:写装饰器,重复执行n次

import functools

def couter(times):   # 带参数的装饰器必须返回一个装饰器, 区别是保留了一个参数times
    def wapper(func):
        @functools.wraps(func)
        def inner(*args, **kwargs):
            for i in range(times):
                result = func(*args, **kwargs)
            return result
        return inner
    return wapper
    
@couter(5)    # 带参数的装饰器 # 执行couter函数,返回值和@结合起来,当做装饰器,
def f1():
    print('f1')

f1()

运行结果:

f1
f1
f1
f1
f1
  • 生成器
    生成器作用:节省空间
    列表:可迭代对象
    应用场景:
    redis中有1000万条数据,全部打印到屏幕。
    redis中的数据存在内存上的,数据太大,不能一次取,通过redis中的hscan_iter的中的生成器,一段一段取出来。
    例:

# 假如redis中数据如下

'''
{

    v1: {
            'n1': 1,
            'n2': 2,
            'n3': 3,
            'n4': 4,
            'n5': 5,
            'n6': 6,
            'n7': 7,
            'n8': 8,
            'n9': 9,
            'n10': 10,
            'n11': 11,
            'n12': 12,
            'n13': 13,
            'n14': 14,
            'n15': 15,
            ...
            'n1000w': 1000w
        }

}
'''


import redis

conn = redis.Redis()

g = conn.hscan_iter(a)  # h:hash  name:v1  count:一次取多少  yield:成了生成器对象

for i in g:     #  写完生成器时没有取值,只有进行迭代时才执行内部的代码
    print(i)

源码解析:

    def hscan_iter(self, name, match=None, count=None):
        """
        Make an iterator using the HSCAN command so that the client doesn't
        need to remember the cursor position.

        ``match`` allows for filtering the keys by pattern

        ``count`` allows for hint the minimum number of returns
        """
        cursor = '0'   # 最开始的位置
        while cursor != 0:
            # [{}, ...] -->  cursor = 100  取完后cursor=0
            cursor, data = self.hscan(name, cursor=cursor,
                                      match=match, count=count)
            for item in data.items():  # 循环每条数据
                yield item  # 往外yield每条数据,一旦yield完再走上面的while循环
  • 迭代器
    for循环内部就是用迭代器,从前到后一个一个获取
    生成器是一种特殊的迭代器,是迭代器的一种
    可迭代对象:类中含有__iter__方法和返回一个迭代器
    普通类:
class F():
    pass

o = F()

for i in o:
    print(i)  # TypeError: 'Foo' object is not iterable 由于不是可迭代对象,所以不可迭代

可迭代对象:

class F():

    def __iter__(self):
        # return iter([1, 2, 3])   # iter()返回一个迭代器,(可以用next获取)
        yield 1
        yield 2
        yield 3  # 由于生成器是迭代器的一种,返回生成器,


o = F()

for i in o:
    print(i)

运行结果:

1
2
3
  • 反射
    getattr
    setattr
    delattr
    hasattr
    应用场景:
    1.django的CBV中:根据method不同找到不同的方法,内部通过getattr找到的

函数补充
2.配置文件setting
python大部分配置文件都用到反射。
如:django的中间件的加载
函数补充

那么他是怎样通过这个字符串找到对应的类呢?
函数补充

其他配置文件的内容也通过字符串反射找到对应的类。如Scrapy框架中的配置文件,DjangoRfw中的配置文件
反射的作用:

相关文章: