面向对象之静态属性与绑定方法

Posted 小狗子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象之静态属性与绑定方法相关的知识,希望对你有一定的参考价值。

静态方法

什么是特性property:

property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

圆的周长和面积:
import math
class Circle:
    def __init__(self,radius): #圆的半径radius
        self.radius=radius

    @property
    def area(self):
        return math.pi * self.radius**2 #计算面积

    @property
    def perimeter(self):
        return 2*math.pi*self.radius #计算周长

c=Circle(10)
print(c.radius)
print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值
print(c.perimeter) #同上
'''
输出结果:
314.1592653589793
62.83185307179586
'''

注意:此时的特性area和perimeter不能被赋值

    c.area=3 #为特性area赋值
    '''
    抛出异常:
    AttributeError: can't set attribute
    '''
为什么要用property

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

除此之外,看下:

ps:面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开

python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现

class Foo:
    def __init__(self,val):
        self.__NAME=val #将所有的数据属性都隐藏起来

    @property
    def name(self):
        return self.__NAME #obj.name访问的是self.__NAME(这也是真实值的存放位置)

    @name.setter  #可以对property的属性方法设置,首先进行了检验,保证了设置的值为int类型
    def name(self,value):
        if not isinstance(value,str):  #在设定值之前进行类型检查
            raise TypeError('%s must be str' %value)
        self.__NAME=value #通过类型检查后,将值value存放到真实的位置self.__NAME

    @name.deleter # 定义不能删除静态属性,抛出异常
    def name(self):
        raise TypeError('Can not delete')

f=Foo('egon')
print(f.name)
# f.name=10 #抛出异常'TypeError: 10 must be str'
del f.name #抛出异常'TypeError: Can not delete'

一 类中定义的方法分为两类:

绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)

1.绑定到类的方法:用classmethod装饰器装饰的方法。为类量身定制.

类.boud_method(),自动将类当作第一个参数传入,(其实对象也可调用,但仍将类当作第一个参数传入)。

2. 绑定到对象的方法:没有被任何装饰器装饰的方法:

为对象量身定制

对象.boud_method(),自动将对象当作第一个参数传入(属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

二:非绑定方法:用staticmethod装饰器装饰的方法:

1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说,就是一个普通工具而已.

注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

绑定给类的方法(classmethod)

classmehtod是给类用的,即绑定到类,类在使用时会将类本身当做参数传给类方法的第一个参数(即便是对象来调用也会将类当作第一个参数传入),python为我们内置了函数classmethod来把类中的函数定义成类方法.

    class Room():
        name = "房子"
    
        def __init__(self, name, type, width, lenth, hight):
            self.name = name
            self.type = type
            self.width = width
            self.lenth = lenth
            self.hight = hight
    
        @property  #静态方法
        def cal_area(self):
            return self.width * self.lenth
    
        def cal_volume(self):
            return self.width * self.hight * self.lenth
    
        @classmethod #类方法
        def tell_info(cls):
            print("类得属性", cls.name, )
            print(cls)# cls.hight  这个是实例的数据属性 类方法调用不到
    

    r1 = Room("alex", "厕所", 100, 100, 1000)
    # print(r1.cal_area)
    
    print(r1.tell_info())  # 实例 方法也可以调用类方法 毕竟实例本身没有方法
    
    # print(Room.tell_info())  # 类调用方法,并且把类本身的数据属性传递给类方法

三 非绑定方法

在类内部用staticmethod装饰的函数即非绑定方法(类的工具包),就是普通函数,statimethod不与类或对象绑定,谁都可以调用,没有自动传值效果。

class Room():
def __init__(self, name, type, width, lenth, hight):
    self.name = name
    self.type = type
    self.width = width
    self.lenth = lenth
    self.hight = hight

@property 
def cal_area(self):
    return self.width * self.lenth

def cal_volume(self):
    return self.width * self.hight * self.lenth

@staticmethod  
def test():
    print("我是静态方法,是类得工具包")  #不能访问类得属性与实例属性

def NOT_test():
    print("我不是静态方法,如果实例调用我 类会自动给实例传递一个参数")


r1 = Room("alex", "厕所", 100, 100, 1000)

print(r1.cal_area)

r1.test()
print(r1.test)  # <function Room.test at 0x00000000011A7840> 普通函数
# r1.NOT_test()   #会报错因为这个实例的类直接把自己自动传给了这个Ttest方法,导致传递多了参数
Room.NOT_test()  # 这个不会报错因为累调用自己的方法  不会把自己传进去

四 classmethod与staticmethod的对比 :

import settings
class mysql:
    def __init__(self,host,port):
        self.host=host
        self.port=port

    @staticmethod
    def from_conf():
        return MySQL(settings.HOST,settings.PORT)

    # @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
    # def from_conf(cls):
    #     return cls(settings.HOST,settings.PORT)

    def __str__(self):
        return '就不告诉你'

class Mariadb(MySQL):
    def __str__(self):
        return '<%s:%s>' %(self.host,self.port)


m=Mariadb.from_conf()
print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你:

以上是关于面向对象之静态属性与绑定方法的主要内容,如果未能解决你的问题,请参考以下文章

30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property

30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property

30.Python面向对象类方法和静态方法动态绑定属性和__slots__限制绑定@property

python之面向对象知识点汇总(小白必会)

面向对象之绑定方法与非绑定方法

面向对象之反射及内置方法