1、类专有的方法
一个类创建的时候,就会包含一些方法,主要有以下方法:
类的专有方法:
方法 | 说明 |
---|---|
__init__ | 构造函数,在生成对象时调用 |
__del__ | 析构函数,释放对象时使用 |
__repr__ | 打印,转换 |
__setitem__ | 按照索引赋值 |
__getitem__ | 按照索引获取值 |
__len__ | 获得长度 |
__cmp__ | 比较运算 |
__call__ | 函数调用 |
__add__ | 加运算 |
__sub__ | 减运算 |
__mul__ | 乘运算 |
__div__ | 除运算 |
__mod__ | 求余运算 |
__pow__ | 乘方 |
当然有些时候我们需要获取类的相关信息,我们可以使用如下的方法:
type(obj)
:来获取对象的相应类型;isinstance(obj, type)
:判断对象是否为指定的 type 类型的实例;hasattr(obj, attr)
:判断对象是否具有指定属性/方法;getattr(obj, attr[, default])
获取属性/方法的值, 要是没有对应的属性则返回 default 值(前提是设置了 default),否则会抛出 AttributeError 异常;setattr(obj, attr, value)
:设定该属性/方法的值,类似于 obj.attr=value;dir(obj)
:可以获取相应对象的所有属性和方法名的列表:
2、方法的访问控制
其实我们也可以把方法看成是类的属性的,那么方法的访问控制也是跟属性是一样的,也是没有实质上的私有方法。一切都是靠程序员自觉遵守 Python 的编程规范。
示例如下,具体规则也是跟属性一样的,
#!/usr/bin/env python # -*- coding: UTF-8 -*- class User(object): def upgrade(self): pass def _buy_equipment(self): pass def __pk(self): pass
3、方法的装饰器
-
@classmethod 调用的时候直接使用类名类调用,而不是某个对象
-
@property 可以像访问属性一样调用方法
具体的使用看下实例:
#!/usr/bin/env python # -*- coding: UTF-8 -*- class UserInfo(object): lv = 5 def __init__(self, name, age, account): self.name = name self._age = age self.__account = account def get_account(self): return self.__account @classmethod def get_name(cls): return cls.lv @property def get_age(self): return self._age if __name__ == '__main__': userInfo = UserInfo('两点水', 23, 347073565); # 打印所有属性 print(dir(userInfo)) # 打印构造函数中的属性 print(userInfo.__dict__) # 直接使用类名类调用,而不是某个对象 print(UserInfo.lv) # 像访问属性一样调用方法(注意看get_age是没有括号的) print(userInfo.get_age)
运行的结果:
1、定义类的继承
首先我们来看下类的继承的基本语法:
class ClassName(BaseClassName): <statement-1> . . . <statement-N>
在定义类的时候,可以在括号里写继承的类,一开始也提到过,如果不用继承类的时候,也要写继承 object 类,因为在 Python 中 object 类是一切类的父类。
当然上面的是单继承,Python 也是支持多继承的,具体的语法如下:
class ClassName(Base1,Base2,Base3): <statement-1> . . . <statement-N>
多继承有一点需要注意的:若是父类中有相同的方法名,而在子类使用时未指定,python 在圆括号中父类的顺序,从左至右搜索 , 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
那么继承的子类可以干什么呢?
继承的子类的好处:
- 会继承父类的属性和方法
- 可以自己定义,覆盖父类的属性和方法
2、调用父类的方法
一个类继承了父类后,可以直接调用父类的方法的,比如下面的例子,UserInfo2
继承自父类 UserInfo
,可以直接调用父类的 get_account
方法。
#!/usr/bin/env python # -*- coding: UTF-8 -*- class UserInfo(object): lv = 5 def __init__(self, name, age, account): self.name = name self._age = age self.__account = account def get_account(self): return self.__account class UserInfo2(UserInfo): pass if __name__ == '__main__': userInfo2 = UserInfo2('两点水', 23, 347073565); print(userInfo2.get_account())
3、父类方法的重写
当然,也可以重写父类的方法。
示例:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- class UserInfo(object): lv = 5 def __init__(self, name, age, account): self.name = name self._age = age self.__account = account def get_account(self): return self.__account @classmethod def get_name(cls): return cls.lv @property def get_age(self): return self._age class UserInfo2(UserInfo): def __init__(self, name, age, account, sex): super(UserInfo2, self).__init__(name, age, account) self.sex = sex; if __name__ == '__main__': userInfo2 = UserInfo2('两点水', 23, 347073565, '男'); # 打印所有属性 print(dir(userInfo2)) # 打印构造函数中的属性 print(userInfo2.__dict__) print(UserInfo2.get_name())
最后打印的结果:
这里就是重写了父类的构造函数。
3、子类的类型判断
对于 class 的继承关系来说,有些时候我们需要判断 class 的类型,该怎么办呢?
可以使用 isinstance()
函数,
一个例子就能看懂 isinstance()
函数的用法了。
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- class User1(object): pass class User2(User1): pass class User3(User2): pass if __name__ == '__main__': user1 = User1() user2 = User2() user3 = User3() # isinstance()就可以告诉我们,一个对象是否是某种类型 print(isinstance(user3, User2)) print(isinstance(user3, User1)) print(isinstance(user3, User3)) # 基本类型也可以用isinstance()判断 print(isinstance('两点水', str)) print(isinstance(347073565, int)) print(isinstance(347073565, str))
输出的结果如下:
True
True
True
True
True
False
可以看到 isinstance()
不仅可以告诉我们,一个对象是否是某种类型,也可以用于基本类型的判断。
多态的概念其实不难理解,它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
事实上,我们经常用到多态的性质,比如:
>>> 1 + 2
3
>>> 'a' + 'b'
'ab'
可以看到,我们对两个整数进行 + 操作,会返回它们的和,对两个字符进行相同的 + 操作,会返回拼接后的字符串。也就是说,不同类型的对象对同一消息会作出不同的响应。
看下面的实例,来了解多态:
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- class User(object): def __init__(self, name): self.name = name def printUser(self): print('Hello !' + self.name) class UserVip(User): def printUser(self): print('Hello ! 尊敬的Vip用户:' + self.name) class UserGeneral(User): def printUser(self): print('Hello ! 尊敬的用户:' + self.name) def printUserInfo(user): user.printUser() if __name__ == '__main__': userVip = UserVip('两点水') printUserInfo(userVip) userGeneral = UserGeneral('水水水') printUserInfo(userGeneral)
输出的结果:
Hello ! 尊敬的Vip用户:两点水
Hello ! 尊敬的用户:水水水
可以看到,userVip 和 userGeneral 是两个不同的对象,对它们调用 printUserInfo 方法,它们会自动调用实际类型的 printUser 方法,作出不同的响应。这就是多态的魅力。
要注意喔,有了继承,才有了多态,也会有不同类的对象对同一消息会作出不同的相应。
最后,本章的所有代码都可以在 https://github.com/TwoWater/Python 上面找到,文章的内容和源文件都放在上面。同步更新到 Gitbooks。