面向对象:三大特性、类成员、property
一、类的基础知识
python 一切皆为对象。
我们以前的str,list,int 都是对象。
1.1 类的定义 与 调用
class 关键字用来定义类,注意类名首字母大写。
类的调用,先实例化一个类,叫做对象或实例。使用这个实例调用其中的方法。
其实在之前我们一直在使用面向对象,str本身就是一个类。
s = ‘abc’ -》 s = str(abc) # 看源码对= 进行了运算符的重载,生成一个对象。就是我们类的调用。
s.upper() 调用里面的方法。
class Foo:
def run(self):
print('run')
obj = Foo()
obj.run()
1.2类 与 实例的存储 self 的含义
在定义类的方法的时候,都需要写一个self,但是在调用的时候又不要写。
其实self就是调用者本身。把self传递给类。self永远是调用者本身。这在继承的时候非常关键。
在python运行的时候,
类存储着本身的各种方法与一些类属性
实例只存储自身的属性,与类的内存指针
当两个实例去调用类里面的方法的时候,使用self传递本身,在调用类中同一个方法,这样在调用的时候就能区别,是谁调用了这个方法。
class Foo:
def run(self, arg):
print(self, arg) obj1 = Foo()
obj1.run(111)
print(obj1)
self
class F: def f1(self):
print('F.f1') def f2(self):
print('F.f2') class S(F):
def s1(self):
print('S.s1') obj = S() obj.s1()
obj.f1() # S中没有f1,F中有,obj去执行,上面的self还是obj
self 永远是调用者本身
二 、面向对象三大特征
面向对象的三大特性:
1. 封装
2.继承
3.多态
2.1 封装
封装是把属性关联到实例(对象)中。下次调用的时候,直接去实例中调用。
python封装分为两种(本质是一样的):
使用构造函数__init__进行封装
动态属性封装
2.1.1 构造方法 __init__
类名+() 就会自动执行__init__
在创建对象(实例化)的时候,类内部会自动调用__init__方法,别名构造方法。利用这个特性我们就可以把属性封装到里面。
封装和构造方法是没有关系的,我们是利用构造方法的特性来封装。
这样所有的实例,都有相同的属性,同时可以通过对象去调用。
class Foo: def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex obj = Foo()
obj.name
2.1.2 动态属性
创建对象之后,动态的添加,但是这种添加只属于该实例本身。
class Foo:
def run(self, arg):
print(self, arg)
obj1 = Foo()
obj1.a = 1
obj1.b = 'abc'
print(obj1.a)
print(obj1.b)
新加的属性,只是保存在这个实例的内存中,其他的实例的内存没有。
但是这种方法,会造成实例属性的不一致,造成管理的难度。一般都是构造函数统一。
在类中有个特殊方法__slots__,可以对动态属性进行了限制。
class Foo:
__slots__ = ('name', 'age', 'sex') # 实例只能有这些属性 def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex obj = Foo('li', 18, 'M')
obj.v = 'v' # 报错,不能添加__slots__以外的动态属性
2.1.3 从封装角度去选择函数 or 面向对象
如果多个函数中有一些相同参数时,就可以把函数转换为面向对象。
如下例子,如果使用函数,ip,port,username,pwd等参数在每个函数中都要去写。
如果转换为面向对象,那么把这些参数封装起来,下面的方法都可以 使用了。
class DataBaseHelper: def __init__(self, ip, port, username, pwd):
self.ip = ip
self.port = port
self.username = username
self.pwd = pwd def add(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接 def delete(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接 def update(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接 def get(self,content):
# 利用self中封装的用户名、密码等 链接数据
print('content')
# 关闭数据链接
2.2 继承
继承就像老子传递给儿子一些东西。 比如金钱,一些习惯。但是一些坏习惯,还有媳妇是不能继承的。
继承遵循开放和封闭原则(修改禁止,支持扩展)。如果一些web框架或其他模块,我们直接下载下来进行修改,部署到生产线上,我们要对所有的web框架的源代码进行修改。
这样很麻烦,而且出现问题的时候,不知道是哪出错了,这时候我们就要使用继承来扩展功能了。
2.2.1 继承的表现形式
class F: def f1(self):
print('F.f1') def f2(self):
print('F.f2') class S(F):
def s1(self):
print('S.s1') obj = S() obj.s1()
obj.f1() # s中没有 f1方法,但是因为继承了,所以也能执行
2.2.2 重写
重写类似与,我不想用父类的方法,想自己写这个方法。只要同名的就可以了。
class F:
def f1(self):
print('F.f1')
def f2(self):
print('F.f2')
class S(F):
def s1(self):
print('S.s1')
def f2(self): # 默认S如果没有重写f2,会执行父类的f2.现在重写了,执行自己的f2.
print('S.f2')
obj = S()
obj.s1()
obj.f1()
2.2.3 执行父类的方法。
执行父类的方法。当我们重写了某个方法,但是又想在这个重写的函数中,执行下父类的该方法。
(一般都这这么使用的,当然也可以执行父类的其他方法。因为默认都继承了父类的方法。只有重写了才需要执行父类的方法)
那我们就可以使用super。
class F:
def f1(self):
print('F.f1')
def f2(self):
print('F.f2') class S(F):
def s1(self):
print('S.s1')
def f2(self):
print('S.f2')
super(S, self).f2() # 执行父类的方法,也可以执行,父类的其他方法
# F.f2(self) # 也可以主动执行,这种方法必须在函数运行时,必须主动传递self。 不推荐这种使用方法。
obj = S()
obj.f2() 运行结果:
S.f2
F.f2
2.2.4 多继承
在java和php其他语言中是不支持多继承的。python和c++支持。
多继承查找规则:
1.左侧的优先,一条路走到底,如果左侧没有,则在右边的执行
2.如果有共同的跟,跟是查找所有之后,最后一步执行的
如上图,如果一个方法只存在Base和F2中,S执行该方法,优先查找F2。如下代码
class base:
def a(self):
print('base.a') class F0(base):
def a1(self):
print('F0.a') class F1(F0):
def a1(self):
print('F1.a') class F2(base):
def a(self):
print('F2.a') class S(F1, F2):
pass s = S()
s.a()
交叉继承实例
多继承一个案列解析(类似socketserver源码):
self永远是执行者本身,调用方法的时候,要从self的类中开始查找该方法。
class BaseRequest():
def __init__(self):
print('BaseRequest.INit') class RequestHandler(BaseRequest): def __init__(self):
print('RequestHandler.init')
super(RequestHandler,self).__init__() def serve_forever(self):
print('RequestHandler.server_forver')
self.process_request() def process_request(self):
print('RequestHandler.process_request') class Minix: def process_request(self):
print('Minix.process_request') class Son(Minix, RequestHandler):
pass obj = Son()
obj.serve_forever() # ,进入到requestHandler中的serve_forver,但是该方法中有个process_request
#self是Son对象,所以又会重新开始查找,根据查找次序,左侧优先,Minix中有。
多继承类似socket源码揭破
2.3 多态
python中不用考虑多态。python原生就是多态的。
java中申明一个变量必须强指定一个类型,函数接受的时候必须严格指定接受参数的类型。
python中一个变量的类型是根据内容进行转换的,在函数接受参数的时候也可以随意。
三、类成员
一个类中有属性和方法,统称为成员。下面我们对类成员进行了简单的分类。
# 属性
- 普通属性,保存在对象中,执行只能通过对象访问 对象实例化时候创建,每个对象有自己一份属性
- 静态属性,保存在类中, 执行可以通过对象访问 也可以通过类访问 类初始化时候创建,所有人共用一份,节约内存# 方法
- 普通方法,保存在类中,由对象来调用,self=》对象
- 静态方法,保存在类中,由类直接调用
- 类方法,保存在类中,由类直接调用,cls=》当前类
class Province:
# 静态属性
country = '中国' def __init__(self, name):
# 普通属性
self.name = name
# 普通方法
def bar(self):
print(self.name)
# 静态方法
@staticmethod
def sta():
print('')
# 类方法
@classmethod
def stac(cls):
print('')
3.1 属性
python中的属性就只有两种类型:普通方法 和 静态方法。
3.1.1 普通属性
在我们利用__init__或动态添加实例的属性,这些都是普通属性,在对象实例化的时候产生,每个对象都有自己一份属性,相互之间不干扰。
3.1.2 静态属性
静态属与类,保存在类中,对象和类都可以访问,在类初始化的时候创建。只保存一份。
当一个对象修改了静态属性,其他看到的都是修改了(后面我们可以把其定义为私有的,避免修改)。
应用场景:所有对象,都有共同的属性,如果用普通属性,每个对象中都会保存一份,大大的消耗内存,这样就可以使用静态属性了。
比如国籍,学校的地址等
3.2 方法
python的方法我们分为三类:普通方法,静态方法,类方法。
3.2.1 普通方法
上面我们定义的都是普通方法,普通方法有两种调用形式:
方法1:
obj = Foo()
obj.run() # 有个self,自动把obj传递过去
方法2:
obj = Foo()
Foo.run(obj) # 手动传递对象,一般都不使用这种方式
3.2.2 静态方法
定义形式:
class Foo:
@staticmethod
def sta():
print('')
不需要传递对象self,就相当于一个普通方法。由类来调用,但是也可以用对象来调用,一般都不这么做。
在一些功能,不依赖于对象中的参数的时候,就可以这么来定义。类似函数,可以自己定义函数参数,不需要self传递东西
3.2.3 类方法
类方法定义:
class Foo:
@classmethod
def stac(cls): # 需要传递一个类
print('')
四、 property
property是一个比较有意思的东西。它是把一个方法 像 属性一样去调用。分页的场景中可以使用。(属性具有 查看,删除,设置方法。)
property其实 就是指定的代码语法 映射到类中指定的方法去接受。 类方法中,想执行什么都是我们自己定义的。
有两种实现方式:
第一种:使用装饰器的方法实现,方法名需要一致。
class Foo:
@property # 映射取值
def per(self):
print('我是不伦不类的', '') @per.setter # 映射设值
def per(self, val):
print(val) @per.deleter # 映射删除
def per(self):
print('我执行了删除') obj.per # 取值
obj.per = '这是啥东西?' # 设值
del obj.per # 删
第二种实现:直接使用内置函数property。代码实现方式:在一些源代码中会这么写。
class Foo:
def f1(self):
return 123 def f2(self, v):
print(v) def f3(self):
print('映射了删除') per = property(fget=f1, fset=f2, fdel=f3) obj = Foo()
obj.per
obj.per = '这是啥东西?'
del obj.per
面向对象:三大特性、类成员、property的更多相关文章
- day20面向对象三大特性 , 类嵌套
#!/usr/bin/env python# -*- coding:utf-8 -*- # 1.简述面向对象三大特性并用代码表示."""封装:class Account: ...
- 面向对象编程(九)——面向对象三大特性之继承以及重写、Object类的介绍
面向对象三大特性 面向对象三大特征:继承 :封装/隐藏 :多态(为了适应需求的多种变化,使代码变得更加通用!) 封装:主要实现了隐藏细节,对用户提供访问接口,无需关心方法的具体实现. 继承:很好的实现 ...
- [.net 面向对象编程基础] (11) 面向对象三大特性——封装
[.net 面向对象编程基础] (11) 面向对象三大特性——封装 我们的课题是面向对象编程,前面主要介绍了面向对象的基础知识,而从这里开始才是面向对象的核心部分,即 面向对象的三大特性:封装.继承. ...
- [.net 面向对象编程基础] (12) 面向对象三大特性——继承
[.net 面向对象编程基础] (12) 面向对象三大特性——继承 上节我们说了面向对象的三大特性之一的封装,解决了将对同一对象所能操作的所有信息放在一起,实现统一对外调用,实现了同一对象的复用,降低 ...
- [.net 面向对象编程基础] (13) 面向对象三大特性——多态
[.net 面向对象编程基础] (13) 面向对象三大特性——多态 前面两节,我们了解了面向对象的的封装和继承特性,面向对象还有一大特性就是多态.比起前面的封装和继承,多态这个概念不是那么好理解.我们 ...
- JAVA基础——面向对象三大特性:封装、继承、多态
JAVA面向对象三大特性详解 一.封装 1.概念: 将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问. 2.好处: 只能通过规定的方法访问数据. ...
- 夯实Java基础系列1:Java面向对象三大特性(基础篇)
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...
- Java面向对象——三大特性
Java面向对象——三大特性 摘要:本文主要介绍了面型对象的三大特性. 封装 什么是封装 封装,就是指一个类隐藏了对象的属性和实现细节,对自己的数据和方法进行访问权限控制,只允许某些类和对象进行访问和 ...
- JavaSE学习笔记(3)---面向对象三大特性
JavaSE学习笔记(3)---面向对象三大特性 面向对象的三大特征:继承.封装.多态 1.封装 面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外界无法直接操作和修改.然 ...
- C++面向对象三大特性
面向对象三大特性 继承 public protected private public继承 public protected 不可见 private继承 private private 不可见 pro ...
随机推荐
- 转:js获取json中key所对应的value值
<script type="text/javascript"> getJson('age'); function getJson(key){ var jsonObj={ ...
- exec-maven-plugin配置及使用
背景: 如果你想在项maven生命周期内,运行一段java代码,或者一段独立的程序,或者说我们所指的预执行,初始化某些值,生成某些不能预先生成的文件.那么这样我们就可以使用exec-maven-plu ...
- vue跳转页面传值怎么传?
这是路由跳转: this.$router.push( { name: 'holderResult', params: { meetingId:self.$route.params.meetingId} ...
- [转]DNS服务器原理详解与Centos6.x下搭建DNS服务器
转自:http://blog.it985.com/8958.html DNS 数据库的记录:正解,反解, Zone 的意义 通过DNS解析过程详解这篇文章,我们知道了要想访问www.zmit.cn,最 ...
- TortoiseSVN_1.9.1.267_x64版本控制系统(针对Visual SVN Server)使用简单介绍
软件下载地址:TortoiseSVN(SVN客户端)64位 V1.9.1.267简体中文免费版 软件详细操作说明:TortoiseSVN使用说明书(超详细) 文章内容:此篇是简单记录如何从Visual ...
- Django学习笔记之Cookie、Session和自定义分页
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- JAVA学习笔记之图解JAVA参数传递
今天做项目,发现了一个问题,当String作为参数传递的时候,在函数内部改变值对外部的变量值无影响,如下代码: public static void main(String[] args) { Str ...
- CSS Position(定位)
CSS Position(定位) 一.CSS Position(定位) position 属性指定了元素的定位类型. position 属性的五个值: static relative fixed ab ...
- The mind
Youtube励志红人Mateusz M,最近刚推出了网友期待已久最新励志短片<The mind>,短短一周播放量已近50万.来自波兰的他,年仅23岁,用自己擅长的蒙太奇,已创作十几个影响 ...
- [BZOJ4566][HAOI2016]找相同子串
COGS传送门 用SAM重新写了一遍.. 我的方法比较笨,先把两个串连在一起,算出来相同子串个数,同理算出s1和s2的子串个数.作差即可. 至于如何统计子串个数,首先toposort后搞出right集 ...