欢迎光临
我们一起进阶

python面向对象——类的专有方法

扫码或搜索:沉默王二
发送 290992
即可立即永久解锁本站全部文章

概述

当类没有继承于任何类时,它默认继承的是系统的object类

在object类中,定义了许多专有方法,它们的方法名是这样的:_ xxx _,左右各有两个下划线;

专有方法不是用来给实例直接调用的,而是有其特定的用途,比如_ init _是在外界调用类名创建实例时调用的;

再比如,当外界print(obj)时,其输出的字符串其实是来源于obj对应的类的_ str _方法的返回值的;

常见专有方法

init : 构造函数,在生成对象时调用
del : 析构函数,释放对象时使用
str:实例的打印样式
len: 获得长度
___ gt___: 比较大小(对象之间进行算术运算后,应返回一个计算后的结果)
add: 加运算
sub: 减运算
mul: 乘运算
mod: 求余运算
pow: 乘方

案例:更加标准化的Person,需求如下:

在创建对象时打印日志
在对象销毁时打印日志
自定义对象的打印样式
设法统计人的“长度”

  1. str

定义一个 Student 类:

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

print(Student('zth'))

执行结果:
<__main__.Student object at 0x03DFDDB0>

1、由上面代码可以看出如果直接输出一个类的实例的话,得到的是一个特殊的字符串(程序开发者所用的)

2、如果要把一个类的实例变成str,就需要实现特殊方法str( )方法

3、str方法必须要return一个字符串类型的返回值,作为对实例对象的字符串描述

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

    def __str__(self):
        return "学生的姓名:%s"%self.name

print(Student('zth'))

执行结果:

学生的姓名:zth

交互模式下:

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...
...     def __str__(self):
...         return "学生的姓名:%s"%self.name
...
>>>
>>> print(Student('zth'))
学生的姓名:zth
>>>
>>> s = Student('zth')
>>>
>>> s
<__main__.Student object at 0x02B10C30>
>>>
>>> print(s)
学生的姓名:zth

原因是直接显示变量调用的不是  str() ,而是 repr(),两者的区别在于str() 返回用户看到的字符串,而 repr() 返回程序开发者看到的字符串。也就是repr() 是为调试服务的。

解决办法是再定义一个repr。通常str() 和 repr() 代码是一样的,可以如下简写:

>>> class Student(object):
...     def __init__(self, name):
...         self.name = name
...
...     def __str__(self):
...         return "学生的姓名:%s"%self.name
...
...     __repr__ = __str__
...
>>>
>>> s = Student('zth')
>>>
>>> s
学生的姓名:zth

  1. iter

如果想要将一个类用于 for … in 循环,类似 list 或 tuple 一样,就必须实现一个iter()  方法。该方法返回一个迭代对象,Python 的 for  循环会不断调用该迭代对象的  next()  方法,获得循环的下一个值,直到遇到 StopIteration 错误时退出循环。

如下:一个作用于 for 循环的斐波那契数列类:

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 n  in Fib():
    print(n)

执行结果:

1
1
2
3
5
8
13
21
34
55
89

  1. getitem

Fib 实例虽然能够作用于 for 循环,和 list 有点像,但是不能将它当成 list 使用。比如取第3个元素:

>>> Fib()[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'Fib' object does not support indexing

若要像list一样按照索引来获取元素,需要实现getitem()方法

>>> class Fib(object):
...     def __getitem__(self,n):
...         a = 0
...         b = 1
...         for x in range(n):
...             a,b = b , a+b
...         return a
...
>>>
>>> fib = Fib()
>>>
>>> fib[3]
2
>>>
>>> fib[5]
5

  1. getattr

正常情况下,调用类的方法或属性时,如果类的方法或属性不存在就会报错。

定义Student类:

>>> class Student(object):
...     def __init__(self):
...             self.name = 'zth'
...
>>>
>>> s = Student()
>>>
>>> s.name
'zth'
>>>
>>> s.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'age'

要避免这个错误,除了可以添加一个score属性外,Python还提供了另一种机制,就是写一个getattr()方法,动态返回一个属性。

>>> class Student:
...     def __init__(self):
...             self.name = 'zth'
...     def __getattr__(self,attr):
...             if attr == 'age':
...                     return 20
...
>>>
>>> s = Student()
>>>
>>> s.name
'zth'
>>> s.age
20

注意,只有在没有找到属性的情况下才调用getattr,已有的属性(如name),不会在getattr中查找。此外,如果所有调用都会返回None(如stu.abc),就是定义的getattr,返回None。

  1. call

一个对象实例可以有自己的属性和方法,调用实例的方法时使用 instance.method() 调用。能不能直接在实例本身调用,答案是可以的。

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

>>> class Student:
...     def __init__(self,name):
...             self.name = name
...     def __call__(self):
...             print('姓名:%s'%self.name)
...
>>>
>>> s = Student('zth')
>>>
>>> s()
姓名:zth

call() 还可以定义参数。对实例进行直接调用就像对一个函数调用一样,完全可以把对象看成函数,把函数看成对象,因为这两者本来就是有根本的区别。

如果把对象看成函数,函数本身就可以在运行期间动态创建出来,因为类的实例都是运行期间创建出来的。 

怎判断一个变量是对象还是函数呢? 
很多时候判断一个对象能否被调用,可以使用Callable()函数,比如函数和上面定义带有call()的类实例。

>>> callable(Student('zth'))
True
>>>
>>> callable(max)
True
>>>
>>> callable([1,3,5])
False
>>>
>>> callable(None)
False

  1. getattr():

getattr( ) 函数用于返回一个对象指定的属性值。如果指定的属性不存在,则返回default的值,若没有设置default参数,则抛出AttributeError异常。以下为该函数的语法:

getattr(object, name[, default])

object -- 对象

name -- 字符串,对象属性。

default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。

返回值:返回对象属性值。

>>> class People:
...     name = 'zth'
...     age = 20
...
>>>
>>> a= People()
>>>
>>>
>>> getattr( a ,'name')
'zth'
>>>
>>> getattr( a ,'class',5)
5
>>>
>>> getattr( a ,'class')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'class'

7 . setattr()

setattr( )函数对应函数getatt(),用于设置指定属性的值,若指定的属性不存在则新建属性并赋值。以下为该函数的语法:

setattr(object, name, value)
 
object — 对象。
 
name — 字符串,对象属性。
 
value — 属性值。
 
返回值:无

>>> class People:
...     name = 'zth'
...
>>>
>>>
>>> a = People()
>>>
>>> setattr(a, 'name','en')
>>>
>>> setattr(a, 'age','20')
>>>
>>> getattr(a,'name')
'en'
>>>
>>> a.age
'20'

8.  delattr()

delattr( )函数用于删除属性,若属性不存在则抛出 AttributeError 异常。以下为该函数的语法:

delattr(object, name)
object — 类名。
name — 必须是对象的属性。
返回值:无
delattr(x, ‘foobar’) 相等于 del x.foobar。

>>> class  People:
...     name = 'zth'
...     age = 20
...
>>>
>>> s = People()
>>>
>>> s.name
'zth'
>>>
>>>
>>> delattr(People, 'name')
>>>
>>> s.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'name'
>>>
>>> del People.age
>>>
>>> s.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'People' object has no attribute 'age'

python类的专有方法就讲完了,其实很简单的,慢慢来~

赞(0) 打赏
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

小白学堂,学的不止是技术,更是前程

关于我们免责声明

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏