带下划线的变量和函数的意义

  • 变量(函数类似)
- 前带单下划线'_'的变量,是一个'私有变量'(语义化),只用于类内部使用,实例还是可以访问到这个变量

- 前带双下划线'__'的变量,是一个'私有变量'(真正的),只用于类内部使用,实例不可以访问到这个变量
    - 其实如果想强行访问,也是可以的...

- '__xxx__':属于python底层代码,一般无需理会

- 测试

class Demo(object):
    # 定义两个私有属性
    _test = '123'
    __number = 456

d = Demo()
print(d._test) # 正常访问
print(d.__number) # 报错

python 另类写法

  • obj.dict: 把 init()中的赋值,打包成dict
class MyResponse():
    
    def __init__(self):
        self.status = 200
        self.msg = None

    @property
    def get_dict(self):
        return self.__dict__

res = MyResponse()
print(res.get_dict) # {'status': 200, 'msg': None}

py解释器阅读的顺序自上而下

- 例子1,不会报错,因为bar已经被加载了

def foo():
    print('from foo')
    bar()

def bar(): # 已经被解释器自上而下,加载到内存
    print('from bar')

foo()  # 不会报错

- 例子2,会报错,因为bar还没加载到内存

def foo():
    print('from foo')
    bar()

foo()  # 报错

def bar():
    print('from bar')

nonlocal 关键字

  • 在嵌套函数中,修改上层函数的变量值

    • 在函数内部定义的变量,默认只在当前函数内部生效
      而无法影响外层函数的变量

    • 使用 nonlocal 关键字,就可以修改外层函数的变量

def myfunc1():
  x = "Bill"
  def myfunc2():
    # nonlocal x
    x = "hello"
  myfunc2()
  return x

print(myfunc1()) # Bill(内层函数变量此时无法修改外层)

def myfunc1():
  x = "Bill"
  def myfunc2():
    nonlocal x
    x = "hello"
  myfunc2()
  return x

print(myfunc1()) # hello(外层函数的变量值被修改了)

什么是闭包函数

- 闭 : 指的是定义在函数内部的函数
- 包 : 闭函数引用了一个来自外层函数的变量
- '总结一句话来说' : 定义在函数内部的函数, 并且该函数包含对外部函数作用域中名字的引用,该函数就称为闭包函数
def outter():
     name='egon'
     def inner():
         print('my name is %s' %name)
     return inner  #注意不能加括号

f=outter() # 返回inner对象
# 注意 : 作用域在函数定义阶段就规定死了, 与调用的位置无关
  • 闭包函数内部,变量的查找顺序
- 先从闭包函数内部找,没有就从外部函数找,最后在函数外面找
- 分别注释x,测试效果

x = 100
def outter():
    x = 2
    def inner():
        x=1
        print('from inner', x)

    return inner

demo = outter()
demo()
  • 功能-获取网页源码演示
### 普通写法: 将"url"以参数的形式传入(也是最常用)
import requests

def get(url):
    response=requests.get(url)下载
    if response.status_code == 200:
        print(response.text)

get('https://www.baidu.com')
get('https://www.python.org')


### 闭包写法
import requests    

def outter(url):
    def get(): # 内层函数引用外层函数的参数,该参数就称为'包'
        response=requests.get(url)
        if response.status_code == 200:
            print(response.text)
    return get
    
baidu = outter('https://www.baidu.com')
baidu()


  • 闭包的用途: 为装饰器作'预备',即不影响原函数的逻辑的前提下,再添加新的功能
import requests    

def outter(url):
    def get(): # 内层函数引用外层函数的参数,该参数就称为'包'
        response=requests.get(url)
        if response.status_code == 200:
            print(response.text)
    '''
    这里可以添加判断,比如url若不符合url正则表达式,就抛异常,从而不再返回 get函数对象
    达到阻止执行get()的逻辑
    '''
    return get
    
baidu = outter('https://www.baidu.com')
baidu()

什么是装饰器

- 器 : 就是工具
- 装饰 : 就是添加新功能
- '总结一句话来说' : 就是定义一个函数, 用该函数去为其他函数添加新功能

- 应用场景: 不修改原函数的源码,不修改原函数的调用方式
  在此基础上,给该函数增加新功能

- 它是闭包函数的升级版...
  • 无参数装饰器写法(在闭包里面,return func函数的计算结果)

def outter(func):
    def wrapper(*args,**kwargs):
        res=func(*args,**kwargs)
        return res
    return wrapper

@outter  # 把 test函数对象当参数,传入
def test():
    print('我是test方法里面的内容')
    return '我是test方法最终返回的内容'

wrapper_func_obj = outter(test) # 返回内层函数对象
print(wrapper_func_obj()) # 执行内层函数逻辑: 我是test方法里面的内容 我是test方法最终返回的内容
  • 计算程序执行时间示例
import time
def timmer(func):
    print('装饰器正在执行')
    def wrapper(*args,**kwargs):
        start_time=time.time()        #开始时间
        res=func(*args,**kwargs)
        stop_time=time.time()         #结束时间
        print(stop_time-start_time)   #使用时间
        return res
    return wrapper

@timmer
def index():
    time.sleep(1)
    print('welcome to index page')
    return 122

index()       # 调用该怎么调还是怎么调

'''
- 执行结果:
	装饰器正在执行
    welcome to index page
    1.0059232711791992

'''

继承需注意的Meta问题

  • 子类继承的时候,如果重写Meta配置项,所有的配置项都会被刷新,没写的项并不会继承父类

    意思就是,该项就没有掉了,程序不会再从父类去找

class Foo(object):
    class Meta:
        xxx = 123
        yyy = 456

class Bar(Foo): # 继承
    class Meta:
        xxx = 100

f = Foo() # f 有 xxx,yyy两个配置项,值分别为 123 和 456
b = Bar() # b 只有 xxx配置项,值为 100;'yyy'配置项是不存在的

print('程序运行结束!')

assert 的用法

  • 通俗理解: 把assert看成if,若条件成立,则正常执行后续代码;否则触发AssertionError异常(可以自定义异常消息)
def test_case(x):
	# 如果条件成立,则执行正常执行后续的语句,不会触发异常
    assert x > 0, "x is not greater than 0"
    return x * 2
    
print(test_case(6)) # 12


def test_case(x):
	# 如果条件不成立,触发异常
    assert x > 0, "x is not greater than 0"
    return x * 2
    
print(test_case(-1)) # AssertionError: x is not greater than 0