首页 / PYTHON / python面向对象
python面向对象
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python面向对象,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含8948字,纯文字阅读大概需要13分钟。
内容图文
Python面向对象
@
目录类
类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。百度百科的解释
Python对于类的实现:
class MyClass:
def method1():
print("method1")
def method2():
print("method2")
#==========分割(上面是类)========
myObj = Myclass()
其中MyClass就是类
对象
对象就是类的实例
上面myObj就是一个对象,它把类Myclass实例化了
类和对象的关系
类相当于是一种构想,一种想象,就很虚无缥缈,Python看到它以后不会给它分配内存空间,而对象就是这种想象的现实体。它们是设计图与实体的关系。
类的方法及其调用
上面的代码中def method1()
和def method2()
就是Myclass类的两个方法,可以通过实例化对象来调用
class MyClass:
def method1():
print("method1")
def method2():
print("method2")
myObj = Myclass()
myObj.method1()
myObj.method2()
与Java类似Python也有构造方法默认的构造方法是init()
,构造方法是每次实例化一个对象的时候都会执行的一个方法,我们可以通过重写它来满足我们的一些要求。例如:
class Myclass:
def __init__(self):
print('正在调用init方法')
这样每次实例化Myclass的时候就会执行print语句。
self
self相当于Java和C++里面的this指针,它就相当于是一个参数,指代当前对象,这个参数的值是在你用这个方法的时候根据对象来传入的。
比如上面的例子
class Myclass:
def __init__(self):
print('正在调用init方法')
myObj = Myclass()
在执行myObj = Myclass()
的时候括号里面虽然没有参数,但是我们能理解成Python自动帮我们把myObj这个参数放入括号传入类里面,self就是指的这个参数,因为类在执行代码的时候需要知道它在操作那块内存,self就是告诉他他要操作哪一块内存。
权限
python里面几乎没有权限控制,它有一个虚假的权限控制手段就是把变量前面加两个下划线__
来完成变量私有化,这个被私有化的变量不能直接从外部访问,只能从内部读取。
class Myclass:
__mysecret = 10
def getmysecret(self):
return self.__mysecret
myObj = Myclass()
try:
myObj.__mysecret
except AttributeError as reason:
print("myObj.__mysecret出错了" + str(reason))
print(myObj.getmysecret())
#只不过是把私有变量改了个名字而已
print(myObj._Myclass__mysecret)
Python的私有变量换了个名字,比如把"__name"就变成了"_类名__name"。
以上代码输出如下
myObj.__mysecret出错了'Myclass' object has no attribute '__mysecret'
10
10
面向对象三大基本特征
封装
封装就是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。
举个例子
class Mysum:
num1 = 2
num2 = 1
num3 = 3
def mysum(self,x, y):
return (x + self.num3) + (y - self.num1 - self.num2)
getSum = Mysum()
ans = getSum.mysum(1, 2)
print(ans)
这个输出肯定是3,但是为什么要用这么愚蠢的算法呢,这不归用户操心,我只需要把这个接口给你,告诉你它是求和的,具体是怎么求的,对你是透明的,你不需要知道实现细节,只需要知道传入两个参数,它会返回它们的和就行,这就是封装。
多态
多态同一个行为具有多个不同表现形式或形态的能力。是指一个类实例(对象)的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。
例如
class cal:
def calu(slef, x):
return 0-x
def calu(self, x, y):
return x + y
test = cal()
print(test.calu(1))
print(test.calu(1, 2))
你以为这个就是python的多态吗,不,错了,这段代码运行会报错,关于多态,Python和Java有天壤之别。
python不支持多态,也不用支持多态,python是一种多态语言,崇尚鸭子类型,一个对象有效的语义,不是有继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。
下面就再解释一下鸭子类型,鸭子类型中关注的不是对象类型本身,而是它是如何使用的,那么python是一门多态语言但是不支持多态就是通过支持鸭子类型来说通的。
举个Java的例子,Java实现多态:
public class test{
public void fun(int x){
System.out.println("输入的参数只有一个");
}
public void fun(int x, int y){
System.out.println("输入的参数有两个")
}
public static void main(String[], args){
test t = new test();
t.fun(1);
t.fun(1, 2);
}
}
/*
=================输出如下==================
输入的参数只有一个
输入的参数有两个
*/
但是python里面这样写是要报错的!
但是Python没必要这样写,它有鸭子类型,它可以这样写:
class A:
def fun(self):
print("A")
class B:
def fun(self):
print("B")
class C(A):
pass
class D(A):
def fun(self):
print("D")
class E():
pass
def getFun(arg):
try:
arg.fun()
except AttributeError as reason:
print("出错了" + str(reason))
a = A()
b = B()
c = C()
d = D()
e = E()
getFun(a)
getFun(b)
getFun(c)
getFun(d)
getFun(e)
getFun('abc')
以下是输出结果
A
B
A
D
出错了'E' object has no attribute 'fun'
出错了'E' object has no attribute 'fun'
很巧妙的小鸭子,注意这个getFun
函数,这种定义方法在不支持鸭子类型的语言里面是绝对不允许的,你给它传入一个参数arg,你却不指定这个参数arg的类型,这好吗,这不好,这容易逻辑混淆,这很好,这也恰恰凸显了python的灵活。
这个函数它不管你传入的是个什么东西,我就把你传进来的参数拿着去找你的fun方法,然后执行它。
如果你是一个对象而且正好有一个fun方法,那我执行那个fun方法。(例如A、B)
什么?你不是一个对象?(python万物皆对象,这里说的可能不是很准确)那我就要报错了。(例如最后一个)
什么?你说你没有这个方法?那我报错。(例如倒数第二个)
什么?你说你没有这个方法但是你爹有?那我不管你爹的就是你的,我执行你爹的。(例如C)
什么?你说你和你爹都有?那简单,你的方法把你爹的覆盖了,执行你的就行。(例如D)
这就是Python的多态。
继承
定义
继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。(百度百科复制过来的定义)
格式
如果A继承B,A是B的子类,则
class A:
def fun(self):
print("A_fun")
class B(A):
pass
b = B()
b.fun
#=======================输出===========
A_fun
就是这样B直接使用A的方法和属性。
重写
class A:
def fun(self):
print("A_fun")
class B(A):
def fun(self):
print("B_fun")
b = B()
b.fun
#=======================输出===========
B_fun
就是如果子类中有方法名和父类一样的的时候,会覆盖掉父类的改方法,这就是重写。
但是不影响父类本身方法。
多继承
Python支持多继承,什么是多继承,就是继承很多个呗,比如
class A:
def fun_A(self):
print("fun_A")
class B:
def fun_B(self):
print("fun_B")
class C:
def fun_C(self):
print("fun_C")
class D:
def fun_A(self):
print("fun_D")
class E(A, B, C, D):
pass
e = E()
e.fun_A()
e.fun_B()
e.fun_C()
#===========输出===============
fun_A
fun_B
fun_C
这就是多继承,相当好理解。
需要注意的是,当父类方法名发生冲突时,继承括号里面排在前面的覆盖后面的。
super关键字
super关键字的用法在Python2和Python3上面有一些不同,这里以Python3为准来描述。
先说一下super在单继承中的用法与意义
提个问题,如果我想在子类的fun方法中调用父类的fun方法怎么办
可以这样写
class A:
def fun(self):
print("A_fun")
class B(A):
def fun(self):
A.fun(self)
print("B_fun")
b = B()
b.fun()
#===========输出结果================
A_fun
B_fun
还可以这样写
class A:
def fun(self):
print("A_fun")
class B(A):
def fun(self):
super().fun()
print("B_fun")
b = B()
b.fun()
那么用super的好处在哪里呢,暂时看不出来,但是当B现在不继承A了,它要继承一个C第二段代码只需要改成class B(C)
而第一段代码还要把A.fun(self)
改成C.fun(self)
,第二段代码可维护性就高了一点。
super在多继承里面可能会稍微复杂那么一丢丢,但是多继承我们能不用就不用,用多了代码越来越混。
组合
当几个类没有明显的继承关系但是又有一定联系的时候就可以用到组合技术
如果继承是纵向深入,组合就是横向扩展。
class count1:
def __init__(self, con1):
self.con1 = con1
class count2:
def __init__(self, con2):
self.con2 = con2
class sum3:
def __init__(self, x, y):
self.x = count1(x)
self.y = count2(y)
self.z = self.x.con1+self.y.con2
def pr(self):
print(self.z)
sum3_a = sum3(2, 3)
sum3_a.pr()
#=======输出==========
5
这就是一个简单的组合__init__
方法前面提到过,是一个构造方法。
python关于面向对象的几个bif
名称 | 参数类型 | 返回值类型 | 作用 |
---|---|---|---|
issubclass(B, A) | B和A都是类 | bool类型 | 判断B是否是A的子类 |
isinstance(x1, A) | x1是实例化对象,A是类 | bool类型 | 判断x1是否是A的实例化对象 |
hasattr(A, s) | A是类,s是字符串 | bool类型 | 判断A里面是否有s属性 |
getattr(x, s1, d) | x是对象,s1是字符串,d可有可无,无所谓 | 属性s1或d | 得到x的s1属性,如果没有就返回d |
setattr(x, s, d) | A是对象,s是字符串,d是属性s | void | 给x添加一个s属性,并且初始值为d |
例子
class A:
pass
class B(A):
pass
print(issubclass(B, A))
x1 = A()
x2 = B()
print(isinstance(x1, A))
print(isinstance(x2, A))
print(isinstance(x1, B))
class D:
def __init__(self, x = 0):
self.x = x
d = D()
print(hasattr(d, 'x'))
print(getattr(d, 'x', "您所访问的属性不存在"))
print(getattr(d, 'y', "您所访问的属性不存在"))
setattr(d, 'y', 1)
print(getattr(d, 'y', "您所访问的属性不存在"))
#==========运行结果==============
True
True
True
False
True
0
您所访问的属性不存在
1
还有一个property,这个描述比较困难就不列表了
class pro:
def __init__(self, va = 10):
self.va = va
def setname(self, va):
self.va = va
def getname(self):
return self.va
def delname(self):
del self.va
pass
x = property(getname, setname, delname)
prop = pro()
print(prop.x)
prop.x = 20
print(prop.x)
del prop.x
try:
print(prop.x)
except AttributeError as reason:
print("出错啦"+str(reason))
#==========运行结果==============
10
20
出错啦'pro' object has no attribute 'va'
这个就是,怎么说呢很方便吧,就是这种格式,操作起来就很方便,而且只需要向外面提过x这一个接口,内部可以大改不用改变很多接口。
内容总结
以上是互联网集市为您收集整理的python面向对象全部内容,希望文章能够帮你解决python面向对象所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。