Python-6-Python面向对象
6-1 面向过程与面向对象
1. 面向过程
面向过程,核心在过程二字,面向过程设计思维,就好比精心设计一条流水线,考虑周全,相应时候处理相应问题。
优点:将复杂问题流程化,进而简单化。
缺点:扩展性差。若更改需求,可能整个代码都需要重写,牵一发而动全身。
若解决不需要经常迭代更新的程序时,面向过程是比较好的,当解决需要频繁迭代更新维护的,使用面向对象比较好。
2. 面向对象
面向对象,是对现实世界的模拟。
面向对象编程的特点:可以编写表示真实世界中事务和情景的类,并基于这些类来创建对象。这可以使程序的维护和扩展变得简单,可大大提高开发效率。
面向对象三大特点:
封装性:使对象的特征与行为保存起来。
继承性:通过继承,子类可快速获取父类的特征与行为。
多态性:不同的子类对象,调用相同的父类方法,产生不同的执行结果。
6-2 创建一个简单的类
类:是描述具有相同特征和行为的对象的集合。格式如下
class 类名(): 变量 #刻画类的特征 def 相关方法(self, 相关参数): #描述类的行为 pass
定义一个简单类:
class Man(): gender = 'male' avg_height = 1.7 def think(self): #实例方法 print('thinking') def sleep(self): prnt('sleeping')
6-3 self 与实例方法
1. 实例方法
man = Man() #实例化一个对象
2. self
self名称是约定成俗的(虽然也可以传其它名字字符串);self是指向类实例化的对象本身;self只会在类的方法中才会有,函数是不必带有self的;self在定义类的方法(实例方法)时是必须的;self在调用时不必传入相应的参数,python会为我们自动传入。
例子:
class Man(): gender = 'male' avg_height = 1.7 def think(self): print('thinking') def sleep(self): print('sleeping') man = Man() man.sleep() print(man.gender) ----------------------- sleeping male
6-4 __init__ 构造函数
使用构造函数,可以让模板生成不同特征的对象。
构造函数格式:
def __init__(self): pass
例子:
class Man(): gender = 'male' #类变量(描述类的通俗特征,只与类有关)###### avg_height = 1.7 def __init__(self, name, age): print('this is __init__()') self.name = name #实例变量(保存对象的具体特征) self.age = age #成员变量也不需要事先定义 def think(self): print('thinking') def sleep(self): print('sleeping') man = Man('xiaohei', 18) man.sleep() print(man.gender) print(man.name) print(man.age) ----------------------- this is __init__() sleeping male xiaohei 18
查看对象:
man.__dict__ #{'name': 'xiaohei', 'age': 18} 查看对象,对象以字典的形式展示,只显示实例变量,不显示类变量 Man.__dict__ #类也可以使用 __dict__方法,会展示很多东西
6-5 通过实例方法访问实例变量与类变量
例子
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): print('this is __init__()') self.name = name self.age = age def think(self): print('thinking') def sleep(self): print('sleeping') def find(self): print('this is ' + str(self.name)) #访问实例变量 print(self.__class__.gender) #访问类变量,法一 print(Man.gender) #访问类变量,法二 print(self.gender) #访问类变量,法三 它会先在构造方法中找,若找不到向上找 man = Man('xiaohei', 18) man.sleep() man.find() print(man.name) ----------------------- this is __init__() sleeping this is xiaohei male male male xiaohei
6-6 类方法
1. 开闭原则:对于扩展是开放的,对于修改是关闭的。
比如要将上面的 avg_height 改为 1.75
man.avg_height = 1.75 #相当于在构造函数中加了一个 self.avg_height = 1.75, 类的 avg_height 还是1.7 man.__dict__ ----------------------- {'name': 'xiaohei', 'age': 18, 'gender': 'renyao', 'avg_height': 1.75}
2. 可以使用类方法来操作类的特征
例子:
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): print('this is __init__()') self.name = name self.age = age def think(self): print('thinking') def sleep(self): print('sleeping') @classmethod #声明定义的是类方法 def modify_height(cls, height): #cls类似self,为了区分写成cls, 表示当前类,也不用传参 cls.avg_height += height print('Now the avg_height is ' + str(cls.avg_height)) Man.modify_height(0.05) Man.__dict__ ----------------------- Now the avg_height is 1.75 ... 'avg_height': 1.75, #类属性已经改过来了
6-7 静态方法
静态方法与普通函数基本上没有什么区别。静态方法与类、对象没有太大关系的时候可以使用该方法。
例子:
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): print('this is __init__()') self.name = name self.age = age def think(self): print('thinking') def sleep(self): print('sleeping') @classmethod def modify_height(cls, height): #cls类似self,为了区分写成cls, 表示当前类,也不用传参 cls.avg_height += height print('Now the avg_height is ' + str(cls.avg_height)) @staticmethod #声明类的静态方法 def plus_num(x, y): print(str(x) + ' + ' + str(y) + ' = ' + str(x+y)) #注意这个打印 return x+y Man.plus_num(2, 3) man = Man('xiaohei', 12) man.plus_num(4, 5) ----------------------- 2 + 3 = 5 this is __init__() 4 + 5 = 9 9
6-8 成员可见性
public: 公开性,外部可以访问相关变量和方法
private:私有性,外部不可以访问相关变量和方法
设置成private的:成员变量或成员方法名前加'__'
例子:
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): self.__name = name #私有成员变量__name self.age = age def __sleep(self): #私有方法 print('sleeping') def get_message(self): print('name= ' + self.__name) #私有成员变量还可以爱成员方法中访问 #__sleep() 加这个也报错,私有成员方法在成员方法内也无法访问吗? TODO: man = Man('xiaohei', 10) # man.__name 私有变量,对外部不可见,包没有属性__name # man.__sleep() 私有方法,对外部不可见 man.get_message() ----------------------- name= xiaohei
6-9 python 没有什么是不能访问的
例子:
man.__dict__ #{'_Man__name': 'xiaohei', 'age': 10} 可以看到多出来了 _Man__name 成员变量,外部可以通过它来访问私有成员变量 man._Man__name #'xiaohei' 外部访问私有成员变量 man._Man__sleep() #sleeping 外部访问私有成员方法
python私有机制做的不是很好,但为了代码规范性,最好还是遵从,Python没有任何机制阻止你访问其私有成员变量和私有成员方法。
6-10 继承
例子:
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): self.name = name self.age = age def think(self): print('thinking') def sleep(self): print('sleeping') class ChinesMan(Man): #继承,ChinesMan 继承 Man pass cman = ChinesMan('xiaobai', 24) cman.think()
继承后重写成员函数:
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): self.name = name self.age = age def think(self): print('thinking') def sleep(self): print('sleeping') class ChinesMan(Man): def __init__(self, name, age, height): self.name = name # 这两行也可以改为调用父类的,使用 Man.__init__(self, name, age); 调用父类方法需要手动传入self self.age = age self.height = height def think(self): # 这里也可以通过 Man.think(self) 调用父类的think() print(self.name + ' is thinking') cman = ChinesMan('xiaobai', 24, 1.8) cman.think() ----------------------- xiaobai is thinking cman.__dict__ # {'name': 'xiaobai', 'age': 24, 'height': 1.8} 可以看到类成员已经变化了
但是 类.构造方法 的调用格式来调用父类的构造方法并不好。其次若这样调用若父类名变了,子类都要进行修改。
6-11 super关键字调用父类方法
super 不仅可以调用父类的构造函数,也可以调用父类的成员方法,可以解决父类名变化带来的影响。
例子:
class Man(): gender = 'male' avg_height = 1.7 def __init__(self, name, age): self.name = name self.age = age def think(self): print('thinking') def sleep(self): print('sleeping') class ChinesMan(Man): def __init__(self, name, age, height): super(ChinesMan, self).__init__(name, age); # super(子类名, self).父类构造方法 调用父类构造方法 self.height = height def think(self): super(ChinesMan, self).think() #使用super后就不需要再传self参数了 调用父类成员函数 print(self.name + ' is thinking') cman = ChinesMan('xiaobai', 24, 1.8) cman.think() ----------------------- thinking xiaobai is thinking
注意:父类必须在子类前面定义,子类可继承一个或多个父类(那此时super调用的是哪个父类的?)
posted on 2023-08-01 15:07 Hello-World3 阅读(8) 评论(0) 编辑 收藏 举报