zl程序教程

您现在的位置是:首页 >  其它

当前栏目

面向对象

面向对象
2023-09-27 14:19:41 时间

一.python面向对象之__slots__

1.为对象和实例添加属性/方法:

python是一种动态编程语言,可以动态为类和实例添加属性.

定义类:

class Dog:
    pass

定义一个方法:

def get_name(self):
    return self.__name

给类动态添加属性和方法:

Dog.__name = 'tiger'
Dog.get_name = get_name

  

#调用
dog = Dog()
print(dog.get_name())

  

输出:
tiger

 

给实例添加属性和方法:

from types import MethodType
dog = Dog()
dog.__name = 'tiger'
dog.get_name = MethodType(get_name, dog)

print(dog.get_name())

  

输出:

tiger

 

2.如果要限制添加的属性怎么办?使用__slots__

示例:

class Dog:
    __slots__ = ('get_name', 'name')

def get_name(self):
    return self.name

  

仅允许为Dog类和实例动态添加get_name和name属性,添加其他属性引发AttributeError错误

dog = Dog()
dog.name = 'tiger'
dog.age = 10
dog.get_name = MethodType(get_name, dog)

print(dog.get_name())

  

输出:
AttributeError: 'Dog' object has no attribute 'name'

 

注意:__slots__不会对继承不起作用,仅对当前类和示例起作用.

 

二.python面向对象之@property

Python内置的@property装饰器就是负责把一个方法变成属性调用

示例:

class Dog:
    def __init__(self):
        self.__age = 0

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, val):
        self.__age = val

dog = Dog()
dog.age = 10
print(dog.age)

  

三.定制类

python为类提供了一些内置属性,可以方便的对类进行定制

1.__str__和__repr__:

__str__:是打印示例输出的内容
__repr__:是在交互命令下输出的实例内容

示例:

class Dog:
    def __str__(self):
        return 'class Dog'
    
    # 直接将__str__属性复制给__repr__
    __repr__ = __str__

dog = Dog()
print(dog)

  

2.__iter__和__next__:

让类可以被迭代

示例代码:

class Dog:
    def __init__(self):
        self.__max = 10
        self.__index = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.__index > 10:
            raise StopIteration()
        tmp = self.__index
        self.__index += 1
        return tmp

dogs = Dog()

for dog in dogs:
    print(dog)

  

输出:

0
1
2
3
4
5
6
7
8
9
10

  

3.__getitem__:

让类可以像list一样取下标和切片

取下标示例代码:

class Dog:
    def __init__(self):
        self.__list = range(10)
    def __getitem__(self, index):
        if index >= len(self.__list):
            raise IndexError()
        return self.__list[index]

dogs = Dog()
print(dogs[1])

  

输出:
1

既可以取下标又可以切片示例代码:

class Dog:
    def __init__(self):
        self.__list = range(10)
    def __getitem__(self, index):
        if isinstance(index, int):
            if index >= len(self.__list):
                raise IndexError()
            return self.__list[index]
        if isinstance(index, slice):
            return list(self.__list)[index.start:index.stop]

dogs = Dog()
print(dogs[1:5])

  

输出:
[1, 2, 3, 4]

4.__getattr__和__setattr__:

__getattr__:但读取属性时,如果不存在则调用
__setattr__:但设置属性时,如果不存在则调用

示例代码:

class Dog(dict):
    def __init__(self):
        self.__name = 'dog'

    def __getattr__(self, item):
        return self[item]

    def __setattr__(self, key, value):
        self[key] = value

dog = Dog()
dog.age = 10
dog.sex = 1

print(dog.age, dog.sex)

  

REST API路径示例:

class Chain:
    def __init__(self, path=''):
        self.__path = path
    def __getattr__(self, item):
        return Chain('%s/%s' % (self.__path, item))
    def __str__(self):
        return self.__path


path = Chain().v1.api.status
print(path)

  


输出:
/v1/api/status

5.__call__

将实例作为函数调用
callable可以判断对象是否可以作为函数调用

示例代码:

class Dog:
    def __call__(self, name):
        print('dog是一条狗,from-%s' % name)

dog = Dog()
if callable(dog):
    dog('dahuang')
else:
    print('not call')