Python 高级编程之面向切面编程 AOP(二)_python aop

和实例方法最大的不同在于,类方法需要使用@classmethod修饰符进行修饰,例如:

class Test:
    #类构造方法,也属于实例方法
    def __init__(self):
        self.name = "Test"
        self.add = "http://www.Test.net"
    #下面定义了一个类方法
    @classmethod
    def info(cls):
        print("正在调用类方法",cls)

if __name__ == "__main__":
    t = Test()
    # 通过对象调用类方法
    t.info()
    # 通过类名调用类方法,类方法推荐直接通过类名调用
    Test.info()
复制代码

注意,如果没有 @classmethod,则 Python 解释器会将 info() 方法认定为实例方法,而不是类方法。

3)静态方法(@staticmethod修饰)

静态方法,其实就是我们学过的函数,和函数唯一的区别是,静态方法定义在类这个空间(类命名空间)中,而函数则定义在程序所在的空间(全局命名空间)中。

静态方法没有类似 self、cls 这样的特殊参数,因此 Python 解释器不会对它包含的参数做任何类或对象的绑定。也正因为如此,类的静态方法中无法调用任何类属性和类方法。

静态方法需要使用@staticmethod修饰,例如:

class Test:
    @staticmethod
    def info(name, add):
        print(name, add)

if __name__ == "__main__":
    c = Test
    # 通过对象调用类方法
    c.info("测试", 123)
    # 通过类名调用类方法(推荐)
    Test.info("hello", "world")
复制代码

四、 property() 函数

传统操作类属性的方式比较麻烦,更习惯使用“类对象.属性”这种方式 , Python 中提供了 property() 函数,可以实现在不破坏类封装原则的前提下,让开发者依旧使用“类对象.属性”的方式操作类中的属性。

property() 函数的基本使用格式如下:

属性名=property(fget=None, fset=None, fdel=None, doc=None)
复制代码
  • fget 参数用于指定获取该属性值的类方法,
  • fset 参数用于指定设置该属性值的方法,
  • fdel 参数用于指定删除该属性值的方法,
  • doc 是一个文档字符串,用于说明此函数的作用。

【注意】在使用 property() 函数时,以上 4 个参数可以仅指定第 1 个、或者前 2 个、或者前 3 个,当前也可以全部指定。也就是说,property() 函数中参数的指定并不是完全随意的。

例如,修改上面的程序,为 name 属性配置 property() 函数:

class CLanguage:
    #构造函数
    def __init__(self,n):
        self.__name = n
    #设置 name 属性值的函数
    def setname(self,n):
        self.__name = n
    #访问nema属性值的函数
    def getname(self):
        return self.__name
    #删除name属性值的函数
    def delname(self):
        self.__name="xxx"
    #为name 属性配置 property() 函数
    name = property(getname, setname, delname, '指明出处')
#调取说明文档的 2 种方式
#print(CLanguage.name.__doc__)
help(CLanguage.name)
clang = CLanguage("C语言中文网")
#调用 getname() 方法
print(clang.name)
#调用 setname() 方法
clang.name="Python教程"
print(clang.name)
#调用 delname() 方法
del clang.name
print(clang.name)
复制代码

五、hasattr()、getattr()、setattr()函数

1)hasattr()

hasattr() 函数用来判断某个类实例对象是否包含指定名称的属性或方法。该函数的语法格式如下:

hasattr(obj, name)
复制代码
  • obj 指的是某个类的实例对象,
  • name 表示指定的属性名或方法名。
  • 同时,该函数会将判断的结果(True 或者 False)作为返回值反馈回来。

示例如下:

class Test001:
    def __init__ (self):
        self.name = "Test001"
        self.add = "http://www.test001.com"
    def say(self):
        print("我正在学Python")

if __name__ == "__main__":
    obj = Test001()
    print(hasattr(obj, "name"))
    print(hasattr(obj, "add"))
    print(hasattr(obj, "say"))
    print(hasattr(obj, "fly"))
复制代码

输出结构:

True
True
True
False
复制代码
2)getattr()

getattr() 函数获取某个类实例对象中指定属性的值。没错,和 hasattr() 函数不同,该函数只会从类对象包含的所有属性中进行查找

getattr() 函数的语法格式如下:

getattr(obj, name[, default])
复制代码
  • obj 表示指定的类实例对象,
  • name 表示指定的属性名,
  • default 是可选参数,用于设定该函数的默认返回值,即当函数查找失败时,如果不指定 default 参数,则程序将直接报 AttributeError 错误,反之该函数将返回 default 指定的值。

示例如下:

class Test002:
    def __init__ (self):
        self.name = "Test002"
        self.add = "http://www.test002.com"
    def say(self):
        print("我正在学Python")

if __name__ == "__main__":
    obj = Test002()
    print(getattr(obj, "name"))
    print(getattr(obj, "add"))
    print(getattr(obj, "say"))
    print(getattr(obj, "display", 'nodisplay'))
复制代码

输出结果:

Test002
http://www.test002.com
<bound method Test002.say of <__main__.Test002 object at 0x00000193F9B98A20>>
nodisplay
复制代码
3)setattr()

setattr() 函数的功能相对比较复杂,它最基础的功能是修改类实例对象中的属性值。其次,它还可以实现为实例对象动态添加属性或者方法。

setattr() 函数的语法格式如下:

setattr(obj, name, value)
复制代码

示例如下:

class Test003:
    def __init__ (self):
        self.name = "Test003"
        self.add = "http://www.test003.com"
    def say(self):
        print("我正在学Python")

if __name__ == "__main__":
    obj = Test003()
    print(obj.name)
    print(obj.add)
    setattr(obj, "name", "Python教程")
    setattr(obj, "add", "http://www.test003.net")
    print(obj.name)
    print(obj.add)
复制代码

输出结果:

Test003
http://www.test003.com
Python教程
http://www.test003.net
复制代码

六、issubclass()和isinstance()函数

Python 提供了如下两个函数来检查类型:

  • issubclass(cls, class_or_tuple):检查 cls 是否为后一个类或元组包含的多个类中任意类的子类。
  • isinstance(obj, class_or_tuple):检查 obj 是否为后一个类或元组包含的多个类中任意类的对象。

示例如下:

# 定义一个字符串
hello = "Hello";
# "Hello"是str类的实例,输出True
print('"Hello"是否是str类的实例: ', isinstance(hello, str))

# "Hello"是object类的子类的实例,输出True
print('"Hello"是否是object类的实例: ', isinstance(hello, object))

# str是object类的子类,输出True
print('str是否是object类的子类: ', issubclass(str, object))

# "Hello"不是tuple类及其子类的实例,输出False
print('"Hello"是否是tuple类的实例: ', isinstance(hello, tuple))

# str不是tuple类的子类,输出False
print('str是否是tuple类的子类: ', issubclass(str, tuple))

# 定义一个列表
my_list = [2, 4]
# [2, 4]是list类的实例,输出True
print('[2, 4]是否是list类的实例: ', isinstance(my_list, list))

# [2, 4]是object类的子类的实例,输出True
print('[2, 4]是否是object类及其子类的实例: ', isinstance(my_list, object))

# list是object类的子类,输出True
print('list是否是object类的子类: ', issubclass(list, object))

# [2, 4]不是tuple类及其子类的实例,输出False
print('[2, 4]是否是tuple类及其子类的实例: ', isinstance([2, 4], tuple))

# list不是tuple类的子类,输出False
print('list是否是tuple类的子类: ', issubclass(list, tuple))
复制代码

七、面向切面编程( AOP )

AOP(Aspect Orentied Programming) 简言之、这种在运行时,编译时,类和方法加载时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。这样对原有代码毫无入侵性。

先来了解一下什么是装饰器吧?

其实上面也通过示例稍微讲解了python自带的几个常用的装饰器函数(@classmethod@staticmethod),其实装饰器是一个很著名的设计模式之一(后面会重点讲解23种设计模式),装饰器经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。简而言之,装饰器的作用就是为已经存在的对象添加额外的功能。

其实上面已经有示例了,那我们再来看几个示例加深一下理解:

import time
 
def timeit(func):
    def wrapper():
        start = time.clock()
        func()
        end =time.clock()
        print 'used:', end - start
    return wrapper
 
@timeit
def foo():
    print 'in foo()'
 
foo()
复制代码

在定义上加上@timeit这一行与另外写foo = timeit(foo)完全等价。

import time
 
def timeit(func):
    def wrapper():
        start = time.clock()
        func()
        end =time.clock()
        print 'used:', end - start
    return wrapper

def foo():
    print 'in foo()'
 
foo = timeit(foo)
复制代码

内置的装饰器有三个,分别是staticmethodclassmethodproperty,作用分别是把类中定义的实例方法变成静态方法、类方法和类属性。其实上面有详细的示例讲解,这里就不再仔细讲解了。再看个示例加深一下理解。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值