python3 入门 (四) 类与继承

Python 类

Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

对象可以包含任意数量和类型的数据。

python类与c++类相似,提供了类的封装,继承、多继承,构造函数、析构函数。

在python3中,所有类最顶层父类都是object类,与java类似,如果定义类的时候没有写出父类,则object类就是其直接父类。

类定义

类定义语法格式如下:

class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

类对象:创建一个类之后,可以通过类名访问、改变其属性、方法

实例对象:类实例化后,可以使用其属性,可以动态的为实例对象添加属性(类似javascript)而不影响类对象。

类的属性

可以使用点(.)来访问对象的属性

也可以使用以下函数的方式来访问属性:

  • getattr(obj, name[, default]) : 访问对象的属性
  • hasattr(obj,name) : 检查是否存在一个属性
  • setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性
  • delattr(obj, name) : 删除属性

Python内置类属性

  • __dict__ : 类的属性(包含一个字典,由类的数据属性组成)
  • __doc__ :类的文档字符串
  • __name__: 类名
  • __module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
  • __bases__ : 类的所有父类构成元素(包含了以个由所有父类组成的元组)
 1 class Person:
 2     "Person类"
 3     def __init__(self, name, age, gender):
 4         print('进入Person的初始化')
 5         self.name = name
 6         self.age = age
 7         self.gender = gender
 8         print('离开Person的初始化')
 9 
10     def getName(self):
11         print(self.name)
12 
13 p = Person('ice', 18, '男')
14 
15 print(p.name)  # ice
16 print(p.age)  # 18
17 print(p.gender)  # 男
18 print(hasattr(p, 'weight'))  # False
19 # 为p添加weight属性
20 p.weight = '70kg'
21 print(hasattr(p, 'weight'))  # True
22 print(getattr(p, 'name'))  # ice
23 
24 print(p.__dict__)  # {'age': 18, 'gender': '男', 'name': 'ice'}
25 print(Person.__name__)  # Person
26 print(Person.__doc__)  # Person类
27 print(Person.__dict__)  # {'__doc__': 'Person类', '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__init__': <function Person.__init__ at 0x000000000284E950>, 'getName': <function Person.getName at 0x000000000284EA60>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__module__': '__main__'}
28 print(Person.__mro__)  # (<class '__main__.Person'>, <class 'object'>)
29 print(Person.__bases__)  # (<class 'object'>,)
30 print(Person.__module__)  # __main__

类的方法

在类地内部,使用def关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数。

类的专有方法:

  • __init__ 构造函数,在生成对象时调用
  • __del__ 析构函数,释放对象时使用
  • __repr__ 打印,转换
  • __setitem__按照索引赋值
  • __getitem__按照索引获取值
  • __len__获得长度
  • __cmp__比较运算
  • __call__函数调用
  • __add__加运算
  • __sub__减运算
  • __mul__乘运算
  • __div__除运算
  • __mod__求余运算
  • __pow__称方

__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法,与c++中构造函数类似。只需在自定义的类中重写__init__()方法即可。

 1 class Person:
 2     def __init__(self, name, age, gender):
 3         print('进入Person的初始化')
 4         self.name = name
 5         self.age = age
 6         self.gender = gender
 7         print('离开Person的初始化')
 8 
 9     def getName(self):
10         print(self.name)
11 
12 # Person实例对象
13 p = Person('ice', 18, '男')
14 print(p.name)
15 print(p.age)
16 print(p.gender)
17 p.getName()
18 
19 # 进入Person的初始化
20 # 离开Person的初始化
21 # ice
22 # 18
23 # 男
24 # ice

析构函数 __del__ ,__del__在对象消逝的时候被调用,当对象不再被使用时,__del__方法运行:

类的封装

python通过变量名命名来区分属性和方法的访问权限,默认权限相当于c++和java中的public

类的私有属性: __private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时self.__private_attrs

类的私有方法:__private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 self.__private_methods

虽然python不允许实例化的类访问私有数据,但可以使用 object._className__attrName 访问属性。其实python内部私有化的实现只是将attrName属性变为了_className__attrName而已

 1 class Demo:
 2     __id = 123456
 3 
 4     def getId(self):
 5         return self.__id
 6 
 7 temp = Demo()
 8 # print(temp.__id)  # 报错 AttributeError: 'Demo' object has no attribute '__id'
 9 print(temp.getId())  # 123456
10 print(temp._Demo__id)  # 123456

类的继承

面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。

需要注意的地方:继承语法 class 派生类名(基类名)://... 基类名写作括号里,基本类是在类定义的时候,在元组之中指明的。

在python中继承中的一些特点:

  • 1:在继承中基类的构造(__init__()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。使用super().__init__()或parentClassName.__init__()
  • 2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
  • 3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。

如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。

语法:

派生类的声明,与他们的父类类似,继承的基类列表跟在类名之后,如下所示:

多态

如果父类方法的功能不能满足需求,可以在子类重写父类的方法。实例对象调用方法时会调用其对应子类的重写后的方法

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏爱撒谎的男孩

插入排序算法

2105
来自专栏啸天"s blog

Java中的关键字

1505
来自专栏用户3030674的专栏

java抽象类和抽象方法之间的关系

抽象类和抽象方法之间的关系 有抽象方法的类,一定是抽象类;抽象类不一定有抽象方法 当子类继承抽象类时,必须要将抽象类中的抽象方法全部实现(或者称为重写),否则子...

1121
来自专栏java一日一条

浅谈Java中的equals和==

为什么第3行和第4行的输出结果不一样?==和equals方法之间的区别是什么?如果在初学Java的时候这个问题不弄清楚,就会导致自己在以后编写代码时出现一些低级...

602
来自专栏Java帮帮-微信公众号-技术文章全总结

07.Java变量类型

07.Java变量类型 Java 变量类型 在Java语言中,所有的变量在使用前必须声明。声明变量的基本格式如下: ? 格式说明:type为Java数据类型。i...

3877
来自专栏一“技”之长

深入理解JavaScript函数 原

    从功能上理解,函数是一组可以随时运行的语句,是一段代码块,也是所谓的子程序。在JavaScript中,函数实质上也是一种对象,是Function对象。函...

621
来自专栏微信公众号:Java团长

浅谈Java中的equals和==

  为什么第4行和第5行的输出结果不一样?==和equals方法之间的区别是什么?如果在初学Java的时候这个问题不弄清楚,就会导致自己在以后编写代码时出现一些...

973
来自专栏Jed的技术阶梯

详解 final 修饰符

被 final 修饰的实例变量必须显示的指定初始值,而且只能在以下3个位置指定初始值:

1514
来自专栏mathor

1小时掌握c++面向对象编程

使用对象指针实参仅将对象的地址值传递给形参,而不进行副本的拷贝,这样可以提高运行效率,减少时间开销

751
来自专栏小樱的经验随笔

【Java学习笔记之二十九】Java中的"equals"和"=="的用法及区别

Java中的"equals"和"=="的用法及区别 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hel...

2927

扫码关注云+社区

领取腾讯云代金券