zoukankan      html  css  js  c++  java
  • 面向对象之类方法、静态方法和属性

    类方法

    什么是类方法?

    类方法是通过类名直接调用的方法,类方法至少有一个参数,第一个参数默认cls(也就是类名),当然对象名也可以调用类方法,但一般不这么用。

    class A:
        name = "barry"
    
        def func1(self):
            print(self)
    
        @classmethod     # 类方法
        def func2(cls):
            print(cls)
    
    
    A.func2()     # <class '__main__.A'>
    
    a = A()
    a.func1()     # <__main__.A object at 0x00000200B267C978>
    a.func2()     # <class '__main__.A'>

    类方法的应用场景

    类方法是将类本身作为对象进行操作的方法。假设有个方法,且这个方法在逻辑上采用类本身作为对象来调用更合理,那么这个方法就可以定义为类方法。另外,如果需要继承,也可以定义为类方法

    静态方法

    什么是静态方法?

    静态方法是类中的函数,不需要实例化(不需要传入self和各种参数)。

    静态方法的应用场景

    静态方法主要用于存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,也就是说在静态方法中,不会涉及到类中的属性和方法的操作。可以理解为,静态方法是个独立、单纯的函数,它仅仅托管与某个类的名称空间中,便于使用和维护。

    比如说,我们想写一个关于时间操作的类,其中有一个获取当前格式化时间的方法

    import time
    
    
    class TimeOperate(object):
        def __init__(self, hour, minute, second):
            self.hour = hour
            self.minute = minute
            self.second = second
    
        @staticmethod
        def showtime():
            return time.strftime("%H:%M:%S", time.localtime())
    
    
    print(TimeOperate.showtime())    # 20:46:54
    
    t = TimeOperate(18, 10, 28)
    current_time = t.showtime()
    print(current_time)    # 20:46:54

    虽然我们也可以在外面定义一个方法来实现同样的功能,但是这样就打乱了逻辑关系,使代码维护起来变得困难

    属性(property)

    什么是属性?

    property是一类特殊的属性,访问时会自动执行一段代码(方法)并返回值,通俗的理解就是property是伪装成属性的方法。

    下面我们来看一个例子,我们要定义一个人类,要求能够获取到一个人的BMI指数,如果不用property,代码是这样的

     1 class Person(object):
     2     def __init__(self, name, weight, height):
     3         self.name = name
     4         self.weight = weight
     5         self.height = height
     6 
     7     def bmi(self):
     8         return self.weight/(self.height**2)
     9 
    10 
    11 p1 = Person("李小龙", 70, 1.80)
    12 print(p1.bmi())    # 21.604938271604937

    虽然这样也可以实现功能,但是不太符合人类是习惯,因为在我们看来,BMI应该是一个静态的属性,就和身高体重一样,应该用对象名.  的方式访问,用property就可以实现,优化后的代码如下

    class Person(object):
        def __init__(self, name, weight, height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property   # 将bmi伪装成属性
        def bmi(self):
            return self.weight/(self.height**2)
    
    
    p1 = Person("李小龙", 70, 1.80)
    print(p1.bmi)     # 这里p1.bmi实际上是执行bmi方法然后返回值给p1.bmi

    使用property的好处

    将一个类的方法定义成属性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则

    由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

    class Goods(object):
        def __init__(self, name, original_price, discount):
            self.name = name
            self.original_price = original_price
            self.discount = discount
    
        @property
        def price(self):
            return self.original_price*self.discount
    
        @price.setter
        def price(self, new_original_price):
            self.original_price = new_original_price
    
        @price.deleter
        def price(self):
            del self.original_price
    
    
    tomato = Goods("西红柿", 3, 0.9)
    print(tomato.price)    # 2.7
    
    # tomato.price = 3.5    # 原价改为3.5
    # print(tomato.price)   # 3.15
    
    del tomato.price     # 删除
    print(tomato.price)     # RecursionError: maximum recursion depth exceeded

     

  • 相关阅读:
    轻量级分布式任务调度框架(二、LTS编译、打包、部署)
    轻量级分布式任务调度框架(一、LTS简介、特点、工作流程)
    MySQL数据库学习一
    Navicat 连接 SQL Server 数据库,报错 08001
    noVNC 遇到一个错误: Uncaught TypeError: Cannot read property 'forEach' of undefined
    加强自己VPS服务器安全的一次经历
    Python 编码错误的本质和解决方案
    You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'data' at line 1
    requests爬虫请求报错:UnicodeEncodeError: 'latin-1' codec can't encode character 'u2026' in position 30
    docker无法删除镜像,Error: No such container,附docker常用命令
  • 原文地址:https://www.cnblogs.com/zzliu/p/10284809.html
Copyright © 2011-2022 走看看