Python装饰器(decorators)

Python装饰器(decorators) 装饰器(decorators)是Python强大的功能之一,语法上就支持(@符号)使用起来更方便,不需要用OOP的设计模式实现。装饰器其实就是个返回函数的函数(类),但可以有很多的玩法,下面将一一介绍。 函数(Functions) 讲装饰器之前,先回顾下一些函数的基础知识,装饰器就是这些简单功能的组合 函数接收函数作为参数 python中定义一个函数很简单如下 >>> def foo(): ... pass ... >>> foo <function foo at 0x1054157a0> >>> bar = foo >>> bar <function foo at 0x1054157a0> 定义了foo函数,而bar是对foo的引用,这很简单 因为python中一切皆对象,函数也是对象,一个函数也可以使用函数作为参数传入,和传其他对象一样(字符串、数字、列表 …) >>> def foo(): ... print("hello world") ... ... >>> def bar(f): ... print(f"call {f.__name__}") ... f() ... ... >>> bar(foo) call foo hello world bar函数就接收foo函数作为参数,内部执行foo函数。 函数内部定义函数 也可以在函数内部定义一个新的函数 >>> def foo(): ... def bar(): ... print("inner func") ... bar() ... ... >>> foo() inner func >>> bar() Traceback (most recent call last): File "<input>", line 1, in <module> bar() NameError: name 'bar' is not defined foo函数中定义了bar函数,定义内部函数和定义在外面的函数没有任何的区别,只是它的作用域只能在foo函数内部,外部是无法应用bar的 函数返回函数 更高级的函数甚至可以返回一个函数作为返回结果 >>> def foo(): ... def bar(): ... return "hello world" ... return bar ... >>> foo <function foo at 0x10c063440> >>> foo() <function foo.<locals>.bar at 0x10baea170> >>> foo()() 'hello world' 注意我们这一次内部不再调用bar()而是return bar,说明foo函数返回一个内部函数的引用 可以看到调用foo()函数返回了内部定义的bar函数(<function foo.<locals>.bar at 0x10baea170>)但没有执行调用,再次调用则会被执行。 ...

April 10, 2017 · 5 min · 902 words · Fython

SSH进阶 端口转发 内网穿透

SSH Tunnel - Port Forwarding Secure Shell (SSH) is a cryptographic network protocol for operating network services securely over an unsecured network. The best known example application is for remote login to computer systems by users. SSH是一个网络协议sftp、scp、ssh都是这个协议。ssh一般用来用于远程主机的登录,Linux系统自带OpenSSH可以方便的使用。它有一个叫SSH Tunnel的东西可以转发流量,下面是几个例子,以便理解和快速使用隧道,详细使用方法,请移步官方手册。 本地端口转发(Local Port Forwarding) -L [bind_address:]port:host:hostport Specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side. 使用-L参数,指定一个本地端口,流量通过这个端口转发到目标主机(host)上的端口(hostport)。 ...

April 8, 2017 · 2 min · 236 words · Fython

《我们仨》杨绛先生回忆录

《我们仨》—— 我一个人思念我们仨 世间好物不坚牢,彩云易散琉璃脆。 这个清明时节没有雨纷纷,三天假期阳光都很好。没有出远门,只回家和家人待了两天,见了几个想见的朋友玩伴。偷空放松下不想学习也看了这本书。 前段时间看《洗澡》当时感觉这书还比他丈夫的《围城》还精彩易读,有可能看《围城》时功力不够不懂钱老师深厚的多国文学基础,有些精细文字也都理解不了,那是一个很遥远的暑假了。看完《洗澡》之后意犹未尽,只想着姚宓与徐彦成精神恋爱的结局,就去看了《洗澡之后》杨绛说“假如我去世以后有人擅写续集,我就无法阻挡了。现在趁我还健在,把故事结束了吧。”多俏皮的话,看完后,还是觉得不要看的好,这部作品就当是百岁老人给我们的开的一个玩笑吧。《我们仨》是杨绛先生在先生和女儿去世之后写的回忆录,是一位孤独老人思念的产物,的确真真实实,历历在目。 书中记录了钱媛先与一九九七年早春去世,一九九八年岁末,钟书去世。她说从此他们三人就此失散了。在短短两年内先后失去两位至亲之人,这悲痛只有当事人能感受得到。并在此后整理钱钟书书信文件出版,并从事文学工作到最后一刻,这就是老一辈知识分子典型代表。 全书一共分为三个部分,前两部是写一个梦。 我曾做过一个小梦,怪他一声不响的走了。他现在故意慢慢儿走,让我一程一程送,尽量多聚聚,把一个小梦拉成一个万里长梦。 我还是比较喜欢第三部,记录他们一家人分分合合,朴实的生活,温暖与亲切。他们都是从剑桥和巴黎留学归来的大学者,也见过大世面,一生不追名逐利,与世无争,与人无求,只求平淡生活。不变的是到哪都会学习、读书和创作。 钟书是坐冷板凳的,他的学问也是冷门。他曾和我说:“有名气就是多些不相识的人。” 我们希望有几个知己, 不求有名有声。 给钟书虚名他都能推就推,只专心做学问。我想正是因为如此他们也躲过了新中国几个困难时期。 比较有趣的是读着读着会想起《洗澡》里的情节阿瑗对我说:“妈妈,我不想结婚了,我陪着爸爸妈妈。”像极了姚蜜说的话。

April 6, 2017 · 1 min · 14 words · Fython

Python中的类变量(class variables)和实例变量(instance variables)

Python中的类变量(class variables)和实例变量(instance variables) 类变量(Class Variables) 类变量是所有实例共享的变量,类和实例都能访问。也就是说类创建了之后类变量就已经初始化了之后所有的实例都共享这个变量不会单独创建。类变量需要定义在类的里面方法的外面 class Foo: cls_var = "this is class method" def __init__(self): pass f0 = Foo() f1 = Foo() print(f0.cls_var, id(f0.cls_var)) print(f1.cls_var, id(f1.cls_var)) print(Foo.cls_var, id(Foo.cls_var)) Foo.cls_var = "changed" print(f0.cls_var, id(f0.cls_var)) print(f1.cls_var, id(f1.cls_var)) print(Foo.cls_var, id(Foo.cls_var)) 输出 this is class method 4328472272 this is class method 4328472272 this is class method 4328472272 changed 4328412136 changed 4328412136 changed 4328412136 类Foo定义了cls_var类变量没有绑定到任何实例,类Foo和实例f0,f1它们引用的变量cls_var都是同一个地址,所以共享一个类变量,只要改变了所有引用的都会影响。以下是统计一共创建了多少实例的例子 class Person: count = 0 # class variable def __init__(self, name): self.name = name Person.count += 1 # 递增 s0 = Person(name="s0") s1 = Person(name="s1") print(Person.count) # 2 __init__构造方法引用Person.count类变量每次实例对象都会自增 实例变量(Instance Variables) 实例变量是每个实例拥有的单独变量在实例创建后才能访问,各个实例变量相互独立。与类变量不同的是实例变量一般定义在方法内(__init__方法) class Person: def __init__(self, name): self.name = name # 实例变量 s0 = Person("student0") s1 = Person("student1") print(s0.name, id(s0.name)) print(s1.name, id(s1.name)) s1.name = "teacher" print(s0.name, id(s0.name)) print(s1.name, id(s1.name)) 输出 ...

March 25, 2017 · 1 min · 191 words · Fython

Python类方法与静态方法的区别 | different between staticmethod and classmethod

Python中的装饰器@staticmethod和@classmethod的区别 staticmethod 当不想访问类变量和实例变量,又想优雅地写代码,方法不写在类外面避免以后代码难以维护。可以这样写封装在类里面 class TestStaticMethod(object): a = 0 def __init__(self): TestStaticMethod.a += 1 @staticmethod def smethod(): print('static method') bar = TestStaticMethod() bar.smethod() TestStaticMethod.smethod() 输出 static method static method [Finished in 0.0s] 静态方法@staticmethod即不能访问类变量也不能访问实例变量,被装饰的方法不需要传入任何参数。类和实例都可以调用。 classmethod 在类中需要用到类变量而不需要实例参与的可以这样写 class TestClassMethod(object): a = 0 def __init__(self): TestClassMethod.a += 1 @classmethod def cmethod(cls): print('class method') # 访问a print(cls.a) foo = TestClassMethod() foo.cmethod() TestClassMethod.cmethod() 输出 class method 1 class method 1 [Finished in 0.0s] 类方法可以引用类变量,但被装饰的方法需要传入类对象参数cls,类和实例都可以调用。 ...

March 20, 2017 · 1 min · 107 words · Fython