1 封装
将具有相同的属性和方法封装为一个数据类型,这个数据类型即为类,类的实例即为对象。
- 类的定义
def 类名(父类名):
pass
注意:没有父类可以不写括号,类名首字母大写。
- 类的实例化
a = Animal() # 实例化一个Animal类
1.1 类属性和实例属性
- python中不需要提前声明属性,可以直接在
__init__()
方法中添加。 - python没有
static
修饰符,但也有类属性和实例属性的区分。
class C:
num = 0
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def foo(self):
print('foo')
@staticmethod
def print_num():
print('the instance number of C is', C.num)
@classmethod
def class_method(cls):
print('this is a @classmethod.')
print(cls.num)
cls().foo()
说明: 类属性:num
(通过C.num
访问)
实例属性:x
、y
- 静态方法有两种:
- 在方法前一行加
@staticmethod
修饰符,静态方法参数不存在self
,即使类实例调用静态方法,该实例也不会传递给静态方法的参数。 - 在方法前一行加
@classmethod
修饰符,函数第一个参数为cls
,表示当前类,可通过cls
调用类的属性和方法。
1.2 变量访问控制
python中没有C++中 private、protected等访问控制的修饰符,但也有一些约定来限制访问:单下划线、双下划线、头尾双下划线:
_foo
:表示protected
类型,只能允许本身和子类访问,不能用于from module import *
。__foo
:表示private
类型,只允许类本身访问,外部不能直接访问,可以通过_类名__foo
访问,但非常不建议。__init__
:表示“魔法方法”。
1.3 魔法方法
这一块主要参考小甲鱼论坛,下面介绍最常用的一些魔法方法。
__new__(cls[, *args, **kwargs])
方法
cls
指代当前类- 类实例化前最先调用该方法
- 该方法返回一个cls的实例,返回值只能调用父类的
__new__()
方法,即:return super().__new__(cls ...)
__init__(self[, *args, **kwargs])
方法
- 该方法是类的构造方法
self
为__new__()
方法返回的实例- 该方法无返回值
举例说明上面两个方法:
class Foo(object):
def __new__(cls):
return object.__new__(Stranger)
def __init__(self):
pass
class Stranger(object):
pass
if __name__ == '__main__':
foo = Foo() # foo类型为Stranger
# 如果cls改为Stranger,则foo类型为Foo
注意:上面两个方法,__new__()
方法调用后,除了cls
参数,其余参数都会传递给__init__()
方法进行初始化,所以:
除了第一个参数,两个方法的其他参数要相同。
__del__(self)
方法
当对象实例对应的内存空间被释放时(引用计数为0),自动调用该方法。(垃圾回收)
class Dog:
def __del__(self):
print('instance is deleted!!')
if __name__ == '__main__':
dog1 = Dog()
dog2 = dog1
del dog1 # 删除dog1,该实例引用计数-1,但还不为0,不会调用__del__()方法
del dog2 # 调用__del__()方法
2 继承和多态
python3定义的类默认继承自object
类,可以显式指定其他父类:
class Animal(object):
def run(self):
print('animal is running!!')
class Dog(Animal):
def run(self):
super().run()
print('The animal is a Dog')
class Cat(Animal):
def run(self):
super().run()
print('The animal is a Cat')
def animal_run(animal):
animal.run()
if __name__ == '__main__':
dog = Dog()
cat = Cat()
animal_run(dog)
animal_run(cat)
鸭子类型:
-
对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用run()方法。
-
对于Python这样的动态语言来说,定义函数不指定参数类型,则不一定需要传入Animal类型。只需要保证传入的对象有一个
run()
方法即可。(多态)
3 获取对象信息
type(object)
:显示对象的类型。isinstance(object, class)
:返回一个对象是否是某种类型。dir(class/object)
:显示类或对象的属性和方法。返回一个listhelp(class/object)
:显示类的内容。class/object.__dict__
:显示类或对象的属性和方法及对应的值。返回一个dict