Python学习笔记二十三(闭包 / 装饰器 )

函数

什么是函数? 将具有某种功能的代码放到一起, 构成一个函数.
为什么说函数? 因为需要研究一个问题, 函数可以嵌套调用, 那么可不可以嵌套定义?

函数的嵌套调用
def func1():
    print("func1")


def func2():
    # 嵌套调用
    func1()


func1()
func2()

# 运行结果
# func1
# func1

函数能使用函数名调用, 那么函数名是什么? 标识符, 标识符里包含变量 / 函数名, 那么函数能不能通过变量传递 / 调用吗?

def func1():
    print("func1")


def func2():
    # 函数通过变量传递
    f2 = func1    
    print("f2 type:%s" % type(f2))
    # 通过变量调用函数
    f2()


func1()
func2()

# 运行结果
# func1
# f2 type:<class 'function'>
# func1

函数可以通过变量传递 / 调用,那么回到最初的问题, 函数能嵌套调用, 函数能嵌套定义吗?

闭包
def func2():
    # 定义函数func1
    def func1():
        print("func1")


func2()

# 运行结果 

通过运行结果可以得出, 可以嵌套定义 ( 没报错:) ) , 那么为什么没有结果?
函数能够传递,函数在定义的时候不会执行, 那么可以明确一点func2 被调用,所以func2 被执行了.
func2 被执行 ,那么func1 定义在func2 函数体内, 所以func1 被定义了, 但是func1 没有被调用.那么能不能通过函数传递调用func1?

def func2():
    # 定义函数func1
    def func1():
        print("func1")

    return func1


f = func2()  # 得到func1 的引用 
print(type(f))  # 查看f 的类型
f()  # 调用函数

# 运行结果
# <class 'function'>
# func1

这种形式叫闭包[1], 在函数内部定义另一个函数, 并且外部函数func2 返回内部函数func1 的引用.
虽然这是一个闭包, 但是没人会这么用, 用两个函数去做一个函数可以完成的事, 而且还这么麻烦.
相信大家都画过数学中的函数图像, 画图像需要确定坐标, 今天就用程序确定 x = 某值时 , y的值 ( y= x的平方 )

def func2(x):
    # 内部函数func1 要使用一个X 的值, 需要从外部传入
    # 为什么要从外部传入?
    def func1():
        print(x ** 2)

    return func1


f = func2(2)  # 得到func1 的引用
f()  # 调用函数

# 运行结果
# 4

一定要从外部传入吗?不一定,就上面这个例子只是简单演示闭包的用法, 而且上面的例子用一个函数也可以完成, 那么闭包大多数的应该用在哪? 装饰器或者叫语法糖.

函数装饰器

只要你写过类方法 / 静态方法, 那么你就用过装饰器.下面来看看装饰器

print("start")  # 开始Debug


# 函数定义 会创建 不会执行
def func2(x):
    print("func2 被调用")
    print("x type = %s" % type(x))

    def func1():
        print("func1 被调用")
        x()

    return func1


@func2  # 程序暂停,执行 func3 = func2(func3)
def func3():
    print("func3 被调用")


func3()  # 调用函数

# 运行结果
# start
# func2 被调用
# x type = <class 'function'>
# func1 被调用
# func3 被调用


装饰器的运行 debug
01装饰器-debug.gif
装饰器运行 图解
02装饰器-图解.png
装饰器运行 文字描述
  • 程序执行到 line:5, func2 被定义 ,
  • 程序执行到 line:16是一个装饰器,不执行,
    • 运行(检测) line:17 定义func3, 同时检测到是一个函数,返回 line:16 执行func2
    • 如果line:17 不是函数,继续向下执行检测,直到遇到函数, 再次返回
  • func2 被执行 ( 因为@func2 ==> func3 = func2(func3) ),
    • x = 原func3 ,既 x 指向原func3 的函数体;
    • print("func2 被调用") # func2 被调用
      print("x type = %s" % type(x)) # x type = <class 'function'>
    • func1 被定义
    • return func1, 既 func3 = func2(func3) = func1,装饰完成func3 被指向func1
  • 程序执行到 line:21,因为func3 在上面被装饰过,所以现在的func3( 装饰完的 ) 指向func1
    • func3() ==> func1(), 既 line:10 被执行, print("func1 被调用")
    • line:11 因为x = 原func3 ,所以 x() 原func3 的方法体被执行, print("func3 被调用")
    • 函数调用完成, 返回被调用处 ,所以 print("func3 被调用") ( line:18) 完成后 返回 x() 处(line:11) ,
    • x() 执行完(line:11) , 返回func3() 处 (line:21), 程序执行完成
特殊记忆方法

根据上面的装饰器运行过程, 我们尝试推出一个方法, 便于记忆和解决装饰器的过程.

03特殊记忆方法.png
使用特殊记忆方法
print("start")  # 开始Debug


# 函数定义 不会执行
def func2(x):
    print("func2 被调用")
    print("x type = %s" % type(x))

    def func1():
        print("func1 被调用")
        x()

    return func1

def func4(x):
    print("func4 被调用")
    print("x type = %s" % type(x))

    def func5():
        print("func5 被调用")
        x()

    return func5
@func4
@func2
def func3():
    print("func3 被调用")


func3()  # 调用函数

# 运行结果
# start
# func2 被调用
# x type = <class 'function'>
# func4 被调用
# x type = <class 'function'>
# func5 被调用
# func1 被调用
# func3 被调用

04特殊记忆方法-使用.png

装饰过程:

  • func3 是一个函数的定义压栈
  • @func2 得到func3 函数的引用 压栈
  • func2 被调用 func1 压栈 ( func2 被调用 x type = <class 'function'>)
  • @func4 的到func1 函数的引用 压栈
  • func4 被调用 func5 压栈 ( func4 被调用 x type = <class 'function'>)

调用过程:

  • 装饰后调用func3 ,func3 指向func5 ,func5被调用
    • func5 出栈, func5 被调用
    • x(),x 指向func1 func1 被调用
  • func1 被调用 func4 出栈 ( 装饰过程,执行过,出栈无效果, 只有func4出栈, func1 在栈顶次可以调用) ,func1 被调用
    • func1 出栈, func1 被调用
    • x(),x 指向func3 func3 被调用

通过上面的我们大概了解装饰过程,以及装饰后的调用过程, 那么如果是有参有返回值的函数怎么装饰呢?

首先我们知道了 闭包外部函数的形参存储着原函数( 被装饰函数) , 闭包内部调用了原函数( 被装饰函数),因为装饰器的调用是由解释器完成的,既@闭包外部函数 , 外部函数的参数个数我们无法改变, 那么只能改变闭包内部函数给 原函数( 被装饰函数)传参.

05传参.png

如图, func3 需要有参数,@func2 的参数个数无法改变, 我们尝试改变func1 的参数,同时x 最终指向原函数,所以x 必须和func3 的参数一致.

print("start")  # 开始Debug


# 函数定义 不会执行
def func2(x):
    def func1(*args, **kwargs):
        print("func1 被调用")
        print("args %s " % args.__str__())
        print("kwargs %s " % kwargs.__str__())
        x(*args, **kwargs)

    return func1


@func2
def func3(*args, **kwargs):
    print("func3 被调用")
    print("args %s " % args.__str__())
    print("kwargs %s " % kwargs.__str__())


func3("Dragon", "Fang", Dragon=18, Fang="nan")  # 调用函数

# 运行结果
# start
# func1 被调用
# args ('Dragon', 'Fang') 
# kwargs {'Dragon': 18, 'Fang': 'nan'} 
# func3 被调用
# args ('Dragon', 'Fang') 
# kwargs {'Dragon': 18, 'Fang': 'nan'} 

通过改变闭包内部函数可以给带参被装饰函数传参, 那么返回值怎么办?

  • 调用函数都会回到被调用处,装饰后func3() 调用,既func1 被调用
  • func1 执行, x() 被调用==>原func3 被调用, 原func3执行完成有返回值,返回到 x() 处,
  • x() 得到值, 如果不将值返回, 那么func1 执行完默认返回None,既 装饰后func3() 处的到None 值,所以 x() 处需要将得到的值返回.
print("start")  # 开始Debug


# 函数定义 不会执行
def func2(x):
    def func1(*args, **kwargs):
        print("func1 被调用")
        return x(*args, **kwargs)

    return func1


@func2
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"


print(func3("Dragon", "Fang", Dragon=18, Fang="nan"))

# 运行结果
# start
# func1 被调用
# func3 被调用
# DragonFang

上面的装饰器可以装饰以下四种函数

  • 无参数,无返回值
  • 无参数,有返回值
  • 有参数,无返回值
  • 有参数,有返回值
装饰器应用场景

装饰器可以在不改变原函数的基础上,添加新的功能 ( 符合开闭原则[2]), 例如计算函数运行耗时, 在优化时常用.

import time


def func(func_args):
    def in_func(*args, **kwargs):
        # 在函数开始运行前,得到当前时间
        start_time = time.time()

        result_value = func_args(*args, **kwargs)

        # 在函数运行结束后,获取当前时间,作差 ==> 得到函数的运行时间
        print(time.time() - start_time)
        return result_value

    return in_func

@func
def test():
    time.sleep(2)

test()

# 运行结果
# 2.00081205368042
函数装饰器-给装饰器传参

有个问题,函数内部嵌套函数的定义是两层, 如果是三层呢?或者更多层呢?先看看三层,三层往上不讨论,层级太深不是一件好事.

def out_test():
    def test(x):
        def in_test(*args, **kwargs):
            print("func1 被调用")
            return x(*args, **kwargs)

        return in_test

    return test 

如上, 三层函数, 首先这是一个函数, 可用通过out_test() 得到test(x) 函数的引用, 然后可以通过test(x) 的到in_test (*args, **kwargs)函数的引用.
那么如果使用这么一个函数作为装饰器,会是什么效果?

06使用三层函数作为装饰器.png

报错?缺少参数?添加参数,添加不定长参数,一步到位 :)

print("start")  # 开始Debug

 
def out_test(*args, **kwargs):
    print("out_test 被调用")

    def test(x):
        print("test 被调用")

        def in_test(*args, **kwargs):
            print("in_test 被调用")
            return x(*args, **kwargs)

        return in_test

    return test


@out_test("Dragon", "Fang", Dragon=18, Fang="nan")
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"


print(func3("Dragon", "Fang", Dragon=18, Fang="nan"))

# 运行结果
# start
# out_test 被调用
# test 被调用
# in_test 被调用
# func3 被调用
# DragonFang

最外层被调用,然后内层被调用, out_test 被调用, 然后 test 被调用, 最后 in_test 被调用, 那么他们分别作了什么事?

def out_test(*args, **kwargs):
    print("out_test 被调用")
    print(args)
    print(kwargs)

    def test(x):
        print("test 被调用")

        print(x)

        def in_test(*args, **kwargs):
            print("in_test 被调用")
            print(args)
            print(kwargs)
            return x(*args, **kwargs)

        return in_test

    return test


@out_test("test", Dragon=20)
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"


print(func3("Dragon", "Fang", Dragon=18, Fang="nan"))

# 运行结果 
# out_test 被调用
# ('test',)
# {'Dragon': 20}
# test 被调用
# <function func3 at 0x000001BAA0C48A60>
# in_test 被调用
# ('Dragon', 'Fang')
# {'Dragon': 18, 'Fang': 'nan'}
# func3 被调用
# DragonFang

out_test 被调用打印了值, 然后test 被调用 , func3 被打印, 因此我们可以推测出@out_test("test", Dragon=20) ==> out_test("test", Dragon=20) 然后 使用 out_test 的返回值对func3 进行装饰

那么可以通过三层函数的形式给装饰器传参.

类装饰器

@classmethod / @staticmethod 都是类装饰器

# classmethod 源码
class classmethod(object):
    """
    classmethod(function) -> method
    
    Convert a function to be a class method.
    
    A class method receives the class as implicit first argument,
    just like an instance method receives the instance.
    To declare a class method, use this idiom:
    
      class C:
          @classmethod
          def f(cls, arg1, arg2, ...):
              ...
    
    It can be called either on the class (e.g. C.f()) or on an instance
    (e.g. C().f()).  The instance is ignored except for its class.
    If a class method is called for a derived class, the derived class
    object is passed as the implied first argument.
    
    Class methods are different than C++ or Java static methods.
    If you want those, see the staticmethod builtin.
    """
    def __get__(self, *args, **kwargs): # real signature unknown
        """ Return an attribute of instance, which is of type owner. """
        pass

    def __init__(self, function): # real signature unknown; restored from __doc__
        pass

    @staticmethod # known case of __new__
    def __new__(*args, **kwargs): # real signature unknown
        """ Create and return a new object.  See help(type) for accurate signature. """
        pass

    __func__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default

    __isabstractmethod__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default


    __dict__ = None # (!) real value is ''

仿照@classmethod ,制作一个类装饰器.

07类装饰器-必须有init魔法方法.png

报错?init魔法方法缺少参数?给参数

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print(args)
        print(kwargs)


@ClassMethod
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"

# 运行结果
# (<function func3 at 0x000001CC350C2E18>,)
# {}

@ClassMethod 调用了init 魔法方法? 那么应该有一个ClassMethod 类的对象被创建,
既@ClassMethod ==> ClassMethod() 得到对象, 使用对象装饰func3.

验证,调用装饰后的func3

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print(args)
        print(kwargs)


@ClassMethod
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"

func3()
# 运行结果
# Traceback (most recent call last):
#   File "E:/workspace/pycharm/pycharm/model.py", line 12, in <module>
#     func3()
# (<function func3 at 0x00000276789F2E18>,)
# TypeError: 'ClassMethod' object is not callable
# {}

报错? 'ClassMethod' object is not callable ,对象不可调用, 证明有一对象被创建, 而且对象需要有一个回调方法. 魔法方法__call__ [3] 可以使一个实例对象变为一个可调用对象.

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print("__init__")
        print(args)
        print(kwargs)

    def __call__(self, *args, **kwargs):
        print("__call__")
        print(args)
        print(kwargs)

@ClassMethod
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"

func3()
# 运行结果
# __init__
# (<function func3 at 0x00000204124F2E18>,)
# {}
# __call__
# ()
# {}

成功运行,证明我们的类装饰器没问题, 那么函数装饰器能传参, 类装饰器怎么传参? call 魔法方法有两个空值, 是不是可以利用一下?

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print("__init__")
        print(args)
        print(kwargs)

    def __call__(self, *args, **kwargs):
        print("__call__")
        print(args)
        print(kwargs)


@ClassMethod("Dragon", "Fang", Dragon=18, Fang="nan")
def func3(*args, **kwargs):
    print("func3 被调用")
    return "DragonFang"


func3()

# 运行结果
# Traceback (most recent call last):
# __init__
#   File "E:/workspace/pycharm/pycharm/model.py", line 19, in <module>
# ('Dragon', 'Fang')
#     func3()
# {'Dragon': 18, 'Fang': 'nan'}
# TypeError: 'NoneType' object is not callable
# __call__
# (<function func3 at 0x000001FCCACB2E18>,)
# {}

call魔法方法被执行, 输出 (<function func3 at 0x000001FCCACB2E18>,) 和 {} ,然后
'NoneType' object is not callable ,空对象不能调用? 我们知道函数 或者方法 默认是有默认返回值的, 默认值是None ,也就是说 call 魔法方法返回了一个None 给调用处,既@ClassMethod("Dragon", "Fang", Dragon=18, Fang="nan") 处, 使用 @None 装饰func3 是不对的, 那么我们返回一个函数, 既使用函数装饰器装饰func3

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print("__init__")
        self.args = args
        self.kwargs = kwargs

    def __call__(self, func):
        print("__call__")
        self.func = func
        return self.test

    def test(self):
        print("test")
        self.func(*self.args, **self.kwargs)


@ClassMethod("Dragon", "Fang", Dragon=18, Fang="nan")
def func3(*args, **kwargs):
    print("func3 被调用")
    print(args)
    print(kwargs)


func3()

# 运行结果
# __init__
# __call__
# test
# func3 被调用
# ('Dragon', 'Fang')
# {'Dragon': 18, 'Fang': 'nan'}

运行成功,给类装饰器传参完成,有几点需要注意

  • 参数,参数是传给init 魔法方法的,需要使用属性接收
  • call 魔法方法返回的是一个函数的引用
  • test方法中,self.func 是原函数, 通过属性传不定长参数需要拆包

类装饰器传参-方式2

上面是在初始化时传参,那能不能将通过方法传参?

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print("__init__")
        self.args = args
        self.kwargs = kwargs

    def __call__(self, func):
        print("__call__")
        self.func = func
        return self.test
    @classmethod
    def test(cls, *args, **kwargs): 
        cls.args = args
        cls.kwargs = kwargs


@ClassMethod.test("Dragon", "Fang", Dragon=18, Fang="nan")
def func3(*args, **kwargs):
    print("func3 被调用")
    print(args)
    print(kwargs)


func3()

# 运行结果
# Traceback (most recent call last):
# test
#   File "E:/workspace/pycharm/pycharm/model.py", line 18, in <module>
#     @ClassMethod.test("Dragon", "Fang", Dragon=18, Fang="nan")
# TypeError: 'NoneType' object is not callable

test 被打印,说明test 类方法被调用, 'NoneType' object is not callable 又是这错误! 给test类方法一个返回值

class ClassMethod(object):
    def __init__(self, *args, **kwargs):
        print("__init__")

        print(args)
        print(kwargs)

    def __call__(self):
        print("__call__")

    @classmethod
    def test(cls, *args, **kwargs):
        cls.args = args
        cls.kwargs = kwargs
        return cls


@ClassMethod.test("Dragon", "Fang", Dragon=18, Fang="nan")
def func3(*args, **kwargs):
    print("func3 被调用")
    print(args)
    print(kwargs)


func3()

# 运行结果
# __init__
# (<function func3 at 0x0000023DD1962E18>,)
# {}
# __call__

通过以上实验可以推断@ClassMethod.test("Dragon", "Fang", Dragon=18, Fang="nan")
==> 先调用test 类方法, 然后 调用 init魔法方法初始化对象, 最后通过实例对象装饰func3
那么按照这个顺序完善一下ClassMethod 类

class ClassMethod(object):
    def __init__(self, func):
        print("__init__")

        self.func = func

    def __call__(self):
        return self.func(*ClassMethod.args, **ClassMethod.kwargs)

    @classmethod
    def test(cls, *args, **kwargs):
        cls.args = args
        cls.kwargs = kwargs
        return cls


@ClassMethod.test("Dragon", "Fang", Dragon=18, Fang="nan")
def func3(*args, **kwargs):
    print("func3 被调用")
    print(args)
    print(kwargs)


func3()

# 运行结果
# __init__
# func3 被调用
# ('Dragon', 'Fang')
# {'Dragon': 18, 'Fang': 'nan'}

perfect 完美

总结:

  • 闭包:函数内部嵌套函数的定义,构成闭包
  • 闭包的作用:大部分用在装饰器
  • 装饰器:@函数名 / @类名 的形式叫做装饰器或者语法糖
  • 装饰器的作用:在不改变原函数的基础上添加功能
  • 装饰前的函数原函数,被闭包外部函数的形参保存
  • 装饰后的函数,实际上是闭包的内部函数,
  • 通用装饰器格式:
# 不需要给装饰器传参
def func(func_args):
    def in_func(*args, **kwargs):
        print("添加功能")
        return func_args(*args, **kwargs)

    return in_func
# 需要给装饰器传参
def out_func(*out_args, **out_kwargs):
    def func(func_args):
        def in_func(*args, **kwargs):
            print("添加功能")
            return func_args(*args, **kwargs)

        return in_func

    return func
  • 装饰器特殊记忆方式,出栈入栈,入栈: 装饰过程,出栈:调用过程
  • 类装饰器,类需要包含 init 魔法方法 和 call 魔法方法 构成基本的类装饰器
  • 类装饰器传参,除了init 魔法方法 和 call 魔法方法 之外需要定义另外的方法
    • @ClassMethod("Dragon", "Fang", Dragon=18, Fang="nan"), 这种传参方式需要定义另外的方法, 辅助调用原函数
    • @ClassMethod.test("Dragon", "Fang", Dragon=18, Fang="nan"), 这种传参方式需要定义另外的方式, 辅助保存参数

到此结 DragonFangQy 2018.5.26


  1. 闭包

  2. 开闭原则

  3. __call__方法

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容

  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,476评论 0 6
  • 某夜R君加班到九点,想来回到宿舍也是孤身一人,定然百无聊奈,加之最近心绪颇不宁静,把自己窝着也只会更添惆怅。...
    谭泽荣阅读 663评论 1 3
  • 打马虎眼,是最近一次会议上,boss给总结的词,再次回忆起来当时情景,仍是羞愧难当。自认为相当负责的我,却是无口否...
    真是奇葩了阅读 1,106评论 0 0
  • 人究竟是怎样一种生物? 我走在人海中, 停下了自己的步伐。 一张张面孔, 迎面走来, 忧愁,喜悦,呆滞,锐利,慈祥...
    海王星1984阅读 245评论 0 1
  • 薛瑞平老师的书确实特别好看。班级日志,阅读课,都是分年级,分学期。有节奏有序列,循序渐进。无论是对工作,还是生活,...
    笑笑8阅读 144评论 0 1