Python进阶丨面向对象高级编程 —— 定制类

本文介绍了Python面向对象编程中的定制类,包括__str__、__iter__、__getitem__、__getattr__和__call__等特殊方法的使用。通过定义这些方法,可以实现自定义类的字符串表示、迭代、下标访问、动态属性获取和对象调用等功能。示例代码展示了这些方法的具体应用。
摘要由CSDN通过智能技术生成

定制类

.

-描述

看到形如__xxx__的变量或者函数名需要注意,这些在Python中是由特殊用途的

  • __str __

class Student(object):
    def __init__(self, name):
        self.name = name

print(Stduent('Maybe')

输出

<__main__.Student object at 0x00000201FC958E48>

可以通过定义__str__()方法,返回指定的字符串

class Student(object):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return 'Student object (name:{})'.format(self.name)

print(Student('Maybe'))

输出

Student object (name:Maybe)

不过不适用print()函数,输出的实例还是没有改变

# Python交互环境
>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...     def __str__(self):
...         return 'Student object (name: %s)' % self.name
>>> s = Student('Michael')
>>> s

输出

<__main__.Student object at 0x00000201FC958E48>

因为直接显示变量调用的不是__str__(),而是__repr__(),两者的区别是__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串

偷懒写法

class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return 'Student object (name={}').format.name
        __repr__ = __str__

.

  • __iter __

如果一个类想被用于for…in循环,类似list或tuple,就必须实现一个__iter__()方法,该方法返回一个迭代对象

# 斐波那契数列
class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a, b
    def __iter__(self):
        return self  # 实例本身就是迭代对象,返回自己
    def __next__(self):
        self.a, self.b = self.b, self.a + self.b
        if self.a > 100: 
            raise StopIteration()
        return self.a # 返回下一个值

for i in Fib():
    print(i)

输出

1
1
2
3
5
8
13
21
34
55
89

.

  • __getitem __

要实现像list那样按照下标取出元素,需要实现__getitem__()方法

class Fib(object):
    def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a + b
        return a

f = Fib()
print(f[3])

输出

3

.

  • __getattr __

正常情况下,调用类的方法或属性时,如果不存在,就会报错。可以通过写一个__getattr__()方法,动态返回一个属性

class Student(object):
    
    def __init__(self):
        self.name = 'Maybe'

    def __getattr__(self, attr):
        if sttr == 'score':
            return 100

s = Student()
print(s.name)
print(s.score)

输出

Maybe
100

也可以返回函数

class Student(object):
    
    def __getattr__(self, attr):
        if attr == 'age':
            return lambda:25

s = Student()

print(s.age()) # 调用方式改为调用函数 

输出

25

注意:只有没有找到属性的情况下,才调用__getattr__,已有的属性,不会在__getattr__中查找

定义的__getattr__默认返回值时None

class Student(object):
    
    def __getattr__(self, attr):
        if attr == 'age':
            return lambda:25

s = Student()
print(s.abc)  # abc属性不存在,返回None

输出

None

要让class只相应特定的几个属性,就按照约定,抛出AttributeError的错误

class Student(object):
    
    def __getattr__(self, attr):
        if attr == 'age':
            return lambda: 25
        raise AttributeError('\'Student\' object has no attribute \'{}\''.format(attr))
 
 s = Student()
 print(s.abc)

输出

AttributeError: 'Student' object has no attribute 'abc'

应用场景

# 链式调用
class Chain(objcet):
    
    def __init__(self, path=''):
        self._path = path

    def __getattr__(self, path):
        return Chain('{}/{}'.format(self._path, path))

    def __str__(self):
        return self._path

    __repr__ = __str__

print(Chain().status.user.timeline.list)

输出

/status/user/timeline/list

.

  • __call __

任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用

class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
       print('My name is {}.'.format(self.name))

s = Stduent('Maybe')
s()

输出

My name is Maybe.

判断一个对象是否能被调用使用Callable

class Student(object):
    def __init__(self, name):
        self.name = name
    def __call__(self):
        print('My name is %s.' % self.name)

print(callable(Student('Maybe')))
print(callable(max))
print(callable(list))
print(callable([1,2,3]))

输出

True
True
True
False
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值