【python语法】python (类与装饰器)的简明案例

类的定义以及类的基础

在写你的第一个类之前,你应该知道它的语法。我们以下面这种方式定义类:

class nameoftheclass(parent_class):
    statement1
    statement2
    statement3
类的继承

当一个类继承另一个类时,它将继承父类的所有功能(如变量和方法)。这有助于重用代码。

在下一个例子中我们首先创建一个叫做 Person 的类,然后创建两个派生类 StudentTeacher。当两个类都从 Person 类继承时,它们的类除了会有 Person 类的所有方法还会有自身用途的新方法和新变量。

#!/usr/bin/env python3

class Person(object):
    """
    返回具有给定名称的 Person 对象
    """

    def __init__(self, name):
        self.name = name

    def get_details(self):
        """
        返回包含人名的字符串
        """
        return self.name


class Student(Person):
    """
    返回 Student 对象,采用 name, branch, year 3 个参数
    """

    def __init__(self, name, branch, year):
        Person.__init__(self, name)
        self.branch = branch
        self.year = year

    def get_details(self):
        """
        返回包含学生具体信息的字符串
        """
        return "{} studies {} and is in {} year.".format(self.name, self.branch, self.year)


class Teacher(Person):
    """
    返回 Teacher 对象,采用字符串列表作为参数
    """
    def __init__(self, name, papers):
        Person.__init__(self, name)
        self.papers = papers

    def get_details(self):
        return "{} teaches {}".format(self.name, ','.join(self.papers))


person1 = Person('Sachin')
student1 = Student('Kushal', 'CSE', 2005)
teacher1 = Teacher('Prashad', ['C', 'C++'])

print(person1.get_details())
print(student1.get_details())
print(teacher1.get_details())

在这个脚本中我们可以看到Student类和Teacher类对于父类Person__init__()方法的调用;还有对父类get_details()方法的重写

当我们调用 student1teacher1get_details() 方法时,使用的是各自类(StudentTeacher)中定义的方法。

多继承

一个类可以继承自多个类,具有父类的所有变量和方法,语法如下:

class MyClass(Parentclass1, Parentclass2,...):
    def __init__(self):
        Parentclass1.__init__(self)
        Parentclass2.__init__(self)
        ...
        ...
删除对象

在python中可以使用 del关键字删除对象

>>> s = "I love you"
>>> del s
>>> s
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 's' is not defined           # 调用 对象 s 的时候发现对象 s 已经被删除了
属性的读取方法

与Java不同,python 在读取属性的时候不需要使用 getterssetters、python 的属性是可以直接调用和修改的

>>> class Student(object):
...     def __init__(self,name):
...         self.name = name
...
>>> std = Student("Kushal Das")
>>> print(std.name)             # 可以通过 . 调取属性
Kushal Das
>>> std.name = "python"
>>> print(std.name)
python

补充:python 装饰器

简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,也就是说 装饰器的运行效果是包裹函数,使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。

比如在记录一个函数执行的时间我们就可以这么做

import time
def func():
    startTime = time.time()
    # 原函数核心代码---开始
    print("hello")
    time.sleep(1)
    print("world")
    # 原函数核心代码---结束
    endTime = time.time()
	# 记录起始时间和结束时间,计算时间差|其中 time.time() 返回当前时间戳(单位ms)
    msecs = (endTime - startTime) * 1000
    print('time is %d ms'%msecs)     # 输出函数执行的时间
func()

在不更改原函数的情况下我们可以直接定义一个计时器函数,并在新定义的函数中调用原函数

#避免直接侵入原函数修改,但是生效需要再次执行函数
import time

def deco(func):     # 自定义计时器函数
    startTime = time.time()
    func()
    endTime = time.time()
    msecs = (endTime - startTime)*1000
    print("time is %d ms" %msecs)


def func():
    print("hello")
    time.sleep(1)
    print("world")

if __name__ == '__main__':
    f = func
    deco(f)     # 只有把func()或者f()作为参数执行,新加入功能才会生效
    print("f.__name__ is",f.__name__)      # f的name就是func
'''
在使用 __name__ 的时候加入当前模块是系统模块,那么此时的模块名称就是__main__;通过 if 可以判断 __main__后面主函数的内容,假如是导入的模块,则这个模块名字就是导入文件的名字(不加后面的py)
1. 如果模块是被导入,__name__的值为模块名字
2. 如果模块是被直接执行,__name__的值为’__main__’
'''

利用装饰器可以更快的将主函数包裹在对应的函数内部执行(这样就不用每次在自定义的计时器函数中调用主函数了;这个计时器函数一旦被装饰器调用,可以适用于任何函数)

import time

def deco(func):
    def wapper():
        startTime = time.time()
        func()       # 调用主函数|包裹主函数的代码是为了统计主函数的执行时间
        endTime = time.time()
        msecs = (endTime - startTime) * 1000
        print("time is %d ms"%msecs)
    return wapper()

# 在主函数上引用装饰器在调用主函数时会先调用装饰器函数(这个案例是在装饰器函数执行过程中执行主函数)
@deco
def func():
    print("hello")
    time.sleep(1)
    print("world")


if __name__ == '__main__':
    f = func
    f       # 这里的 func 被实例化为 f 执行 f 就是执行 func

这里的 deco 就相当于一个装饰器,它的参数是一个函数,然后也返回一个函数,其中作为装饰器函数参数的函数也就是被统计上执行时间的主函数func在装饰器函数的wrapper内执行(相当于函数被注入了计时器功能),仙子啊只要调用func,他就已经是功能更多的函数了

装饰器就相当于是一个给函数诸如功能的符号,拓展原来的函数功能ing且不需要侵入函数内(修改主函数代码)也不需要重复执行函数

案例:带有不定参数的装饰器

#多个装饰器

import time

def deco01(func):     # 装饰器的参数要是函数
    def wrapper(*args, **kwargs):  
        print("this is deco01")
        startTime = time.time()
        func(*args, **kwargs)
        endTime = time.time()
        msecs = (endTime - startTime)*1000
        print("time is %d ms" %msecs)
        print("deco01 end here")
    return wrapper

def deco02(func):
    def wrapper(*args, **kwargs):  # 函数可以带有不定参数
        print("this is deco02")
        func(*args, **kwargs)

        print("deco02 end here")
    return wrapper

@deco01
@deco02
def func(a,b):
    print("hello,here is a func for add :")
    time.sleep(1)
    print("result is %d" %(a+b))



if __name__ == '__main__':
    f = func
    f(3,4)
    

从这个函数的执行结果可以看出:

this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1000 ms
deco01 end here

当函数使用多个装饰器的时候,正确的调用顺序时从最后一个装饰器开始,到第一个装饰器,直到函数本身执行完毕;

import time


def dec1(func):
    print("1111")
    def one():
        print("2222")
        func()
        print("3333")
    return one


def dec2(func):
    print("aaaa")
    def two():
        print("bbbb")
        func()
        print("cccc")
    return two

@dec1
@dec2
def demo():
    print("test  test")

demo()
# 函数的执行结果是:
aaaa
1111
2222
bbbb
test  test
cccc
3333
# 先执行 dec2的内容,再执行dec1的内容 最后执行 demo函数本身

使用装饰器和类的思想写一个将美元转换成人民币的案例

#!/usr/bin/env python3

class Account(object):
    """
    __amt: 当前用户账户中的美元存量
    rate:美元与人民币兑换比率
    """
    def __init__(self,rate):
        self.__amt = 0
        self.rate = rate

    @property
    def amount(self):
        '''  这个方法返回当前用户的美元存量 通过这个方法修改这一条属性 '''
        return self.__amt

    @property
    def cny(self):
        """ 计算美元兑换成人民币的比率,通过这个方法计算出结果并返回给 cny """
        return self.__amt * self.rate

    @amount.setter
    def amount(self,value):
        if value < 0:
            print("Sorry , no negative amount in your account")
            return     #
        self.__amt = value

if __name__ == '__main__':
    acc = Account(rate=6.6)
    acc.amount = 20
    print("Dollar Amount:",acc.amount)
    print("In CNY:",acc.cny)
    acc.amount = -100
    print("Dollar Amount:",acc.amount)

案例中引用了 python自带的装饰器,装饰器的用法下期 会说(python 常见的装饰器)

遇见的 BUG 和解决的方法

在编程的过程中出现了以下 bug :

ModuleNotFoundError: No module named 'pytest’

解决的方法:不要使用test作为函数名称;否则python解释器会出现找不到 pytest 模块的错误

TypeError: ‘NoneType’ object is not callable

解决方法:在调用函数的时候(或者调用函数实例化的对象时)不要加()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值