python __slots__和@property

前面了解了python的面向对象的基本方式https://blog.csdn.net/qq_21294095/article/details/85118247

心中有挺多的疑问,而解决这些疑问就需要用到python更强大的功能了


一,动态绑定这个事儿太随意了,怎么限制?

__slots__属性可以用来限制动态绑定可以绑定的属性,哪怕是在类内部,也要遵守这个规定。

class Animal(object):
    __slots__ = ('name', 'age')

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

animal = Animal('佩奇',4)
print(animal.legs)

Output:
AttributeError: 'Animal' object has no attribute 'legs'

可以看到,因为初始化的时候绑定了__slots__没有指定的属性legs,所以出错。

需要注意:

__slots__会被子类继承过去,但是子类自己的__slots__没有做限制,所以父类的__slots__对子类就起不了作用。

class Animal(object):
    __slots__ = ('name', 'age')

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

class Dog(Animal):
    pass

dog = Dog('八公')
dog.legs = 4
print(dog.legs)

Output:
4

需要在子类也指定__slots__, 然后子类的属性限定就是父类的并上自己的__slots__

class Animal(object):
    __slots__ = ('name', 'age')

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

class Dog(Animal):
    __slots__ = ('size')
    pass

dog = Dog('八公')
dog.legs = 4
print(dog.legs)

Output:
AttributeError: 'Dog' object has no attribute 'legs'

二,python中的setter和getter

给类创建了属性之后,用封装的思想,那么就需要提供setter和getter方法。python可以想常规的那样提供这两个方法:

class Animal(object):

    def getName(self):
        return self.name

    def setName(self, name):
        if isinstance(name, str): #这里简单模拟一下设置值的时候的限制 只有是str才可以设置
            self.name = name
        else:
            self.name = '默认名称'

animal = Animal()

animal.setName(300)
print(animal.getName())
animal.setName('三毛')
print(animal.getName())

Output:
默认名称
三毛

其实没什么问题,就是调用的时候有些麻烦。而python是个追求简单完美的语言,那么麻烦就不能允许。于是python就提供了一个装饰器@property来避免这个麻烦

class Animal(object):

    @property
    def getName(self):
        return self.name

    @getName.setter
    def setName(self, name):
        if isinstance(name, str): #这里简单模拟一下设置值的时候的限制 只有是str才可以设置
            self.name = name
        else:
            self.name = '默认名称'

animal = Animal()

animal.setName = 300
print(animal.getName)
animal.setName = '三毛'
print(animal.getName)

Output:
默认名称
三毛

这里只做了简单的修改,可以看到,setter和getter两个方法名都被装饰器变成了属性,并且由于是装饰器,所以原有的功能都保留了下来。看到这里,你肯定会说,这有什么用?感觉代码变得更难以理解了。不急,继续修改下去:

class Animal(object):

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, name):
        if isinstance(name, str): #这里简单模拟一下设置值的时候的限制 只有是str才可以设置
            self.__name = name
        else:
            self.__name = '默认名称'

animal = Animal()

animal.name = 300
print(animal.name)
animal.name = '三毛'
print(animal.name)

Output:
默认名称
三毛

怎么样?这下代码是不是特别清晰,然而实际上就是把setter和getter方法重载,这样就有一样的函数名,接着把真正需要的属性__私有化,(当然这个私有化前文说过,你有办法去访问)而已。如果直接上这段代码,会体会不到@property到底做了哪些事情,那么它做了哪些事情?

  1. @property 把getter方法变成属性 并且创建了另一个装饰器:@属性.setter
  2. @属性.setter 把setter方法变成属性 

猜你喜欢

转载自blog.csdn.net/qq_21294095/article/details/85121272