首页 > 其他分享 >15.面向对象和super

15.面向对象和super

时间:2023-06-30 21:11:44浏览次数:39  
标签:__ 15 self add 面向对象 init print super def

面向对象和super()

类(Class): 具有相同的属性和方法的对象的集合,即定义对象的模板

对象(Object): 类的实例化对象,有自己的属性和方法。

类方法: 使用装饰器@classmethod ,传递类的属性和方法(不能传实例的属性和方法)

类属性: 类中的变量。类变量在整个实例化的对象中是公用的

实例方法: 传递对象的属性和方法

实例属性: 使用 self 调用

封装:对外部世界隐藏对象的工作细节
多态:对不同类的对象使用同样的操作
继承:即一个派生类(derived class)继承基类(base class)的字段和方法
class Person():
    # #类属性
    name="小明"
    age=12   
    
    def __init__(self,id,email):
        实例属性
        self.id=id
        self.email=email
    
    实例方法
	def run(self):
        pass
    
xiaomi=Person(110,'110.com')    # 对象实例化
xiaomi.colour='red' 	        # 添加属性

print(Person.name)         # 类引用

类对象支持两种操作:属性引用和实例化

class Circle(object):  # 创建Circle类
   def __init__(self, r): # 初始化一个属性r(不要忘记self参数,他是类下面所有方法必须的参数)
       self.r = r  # 表示给我们将要创建的实例赋予属性r赋值
  • self 和对象 指向了同一个内存地址,对对象的引用
  • self代表类的实例,而非类

实例属性用于区分不同的实例
类属性是每个实例的共有属性。

保留关键字对实例的操作

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

class Person():
    def __init__(self, name,home):
        self.name=name
        self.home=home
        print('我是Peson的__init__构造方法')

    def address(self):
        print("Name : ", self.name, ", address: ", self.home)



p1=Person("bei","BeiJing")
p1.address()
p1.age=18
p1.age=27

print(hasattr(p1, 'age')) # 如果存在 'age' 属性返回 True。
print(getattr(p1, 'age')) # 返回 'age' 属性的值

print(setattr(p1, 'age', 8))  # 添加属性 'age' 值为 8
print(delattr(p1, 'age'))     # 删除属性 'age'

# 执行结果
我是Peson的__init__构造方法
Name :  bei , address:  BeiJing
True
27
None
None
hasattr(emp1, 'age')    # 如果存在 'age' 属性返回 True。
getattr(emp1, 'age')    # 返回 'age' 属性的值
setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8
delattr(emp1, 'age')    # 删除属性 'age'

内置属性类

__dict__ : 类的属性(包含一个字典,由类的数据属性组成)
__doc__ :类的文档字符串
__name__: 类名
__module__: 类定义所在的模块(类的全名是'main.className',如果类位于一个导入模块mymod中,那么className.module 等于 mymod)
__bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

class Person():
    def __init__(self, name,home):
        self.name=name
        self.home=home
        print('我是Peson的__init__构造方法')

    def address(self):
        print("Name : ", self.name, ", address: ", self.home)

p1=Person("bei","BeiJing")

print ("Person.__doc__:", Person.__doc__)
print ("Person.__name__:", Person.__name__)
print ("Person.__module__:", Person.__module__)
print ("Person.__bases__:", Person.__bases__)
print ("Person.__dict__:", Person.__dict__)

# # ====================================================================
我是Peson的__init__构造方法
Person.__doc__: None
Person.__name__: Person
Person.__module__: __main__
Person.__bases__: (<class 'object'>,)
Person.__dict__: {'__module__': '__main__', '__init__': <function Person.__init__ at 0x000002619C7CD5E0>, 'address': <function Person.address at 0x000002619C8B3DC0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}

私有属性和私有方法

__foo__: 定义的是特殊方法,一般是系统定义名字 ,类似 __init__() 之类的。

_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于

from module import *

__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问

私有属性包括 类属性和实例对象属性
私有方法包括 类方法和实例对象方法

双下划线
class Student():
	name="zhangsan"
	__age=12
	def __init__(self):
		__add="大红门"
        pass
    
	def __eat(self):
        pass
    pass

只能类的内部使用,不能在外部使用
1、不能被子类继承
2、不能实例调用

property

针对私有属性
property(get_day,set_day)

可以通过在类中定义__slots__变量来进行限定
 # 限定Person对象只能绑定_name, _age和_gender属性
    __slots__ = ('_name', '_age', '_gender')

super()

super() 是python 中调用父类(超类)的一种方法,在子类中可以通过super()方法来调用父类的方法。【超类: 是指 2层以上的继承关系,假如 C类继承B类,B类由继承A类,那么A类就是C类的超类】

通过super() 来调用父类的__init__ 构造方法

class Person():
    def __init__(self, name):
        print('我是Peson的__init__构造方法')


class Student(Person):
    def __init__(self, name):
        super(Student).__init__(name)
        print('我是Student的__init__构造方法')


class Teacher(Student):
    def __init__(self, name):
        super(Teacher).__init__(name)
        print('我是Teacher的__init__构造方法')


stu = Teacher(name="beike")
# 执行结果================================================================
我是Peson的__init__构造方法
我是Student的__init__构造方法
我是Teacher的__init__构造方法

通过supper() 来调用与子类同名的父类方法

class A:
    def __init__(self):
        self.n = 2

    def add(self, m):
        print('self is {0} @A.add'.format(self))
        self.n += m


class B(A):
    def __init__(self):
        super(B, self).__init__()
        self.n = 3

    def add(self, m):
        print('self is {0} @B.add'.format(self))
        super().add(m)
        self.n += 3


b = B()
b.add(2)
print(b.n)
# 执行结果=========================================================================
self is <__main__.B object at 0x106c49b38> @B.add
self is <__main__.B object at 0x106c49b38> @A.add
8

1、super().add(m) 确实调用了父类 A 的 add 方法。
2、super().add(m) 调用父类方法 def add(self, m) 时, 此时父类中 self 并不是父类的实例而是子类的实例, 所以 b.add(2) 之后的结果是 5 而不是 4 。

多继承

针对 菱形继承
钻石继承还有一个问题是,比如若B和C中的m方法也同时调用了A中的m方法时:

class A:
    def m(self):
        print("m of A called")

class B(A):
    def m(self):
        print("m of B called")
        A.m(self)

class C(A):
    def m(self):
        print("m of C called")
        A.m(self)

class D(B,C):
    def m(self):
        print("m of D called")
        B.m(self)
        C.m(self)
        
# 此时我们调用d.m,A.m则会执行两次。
d=D()
d.m()
# 执行结果 ===============================================================
m of D called
m of B called
m of A called
m of C called
m of A called

在多继承中,会涉及到一个MRO(继承父类方法时的顺序表) 的调用排序问题。即严格按照MRO 顺序执行super方法

其实上面两个问题的根源都跟MRO有关,MRO(Method Resolution Order)也叫方法解析顺序,主要用于在多重继承时判断调的属性来自于哪个类,其使用了一种叫做C3的算法,其基本思想时在避免同一类被调用多次的前提下,使用广度优先和从左到右的原则去寻找需要的属性和方法。

class A:
    def __init__(self):
        self.n = 2

    def add(self, m):
        print('self is {0} @A.add'.format(self))
        self.n += m

class B(A):
    def __init__(self):
        super(B, self).__init__()
        self.n = 3

    def add(self, m):
        print('self is {0} @B.add'.format(self))
        super().add(m)
        self.n += 3

class C(A):
    def __init__(self):
        super(C, self).__init__()
        self.n = 4

    def add(self, m):
        print('self is {0} @C.add'.format(self))
        super().add(m)
        self.n += 4

class D(B, C):
    def __init__(self):
        super(D, self).__init__()
        self.n = 5

    def add(self, m):
        print('self is {0} @D.add'.format(self))
        super().add(m)
        self.n += 5

d = D()
d.add(2)
print(d.n)

# # =================================================================================
self is <__main__.D object at 0x000001DC8F4F9700> @D.add
self is <__main__.D object at 0x000001DC8F4F9700> @B.add
self is <__main__.D object at 0x000001DC8F4F9700> @C.add
self is <__main__.D object at 0x000001DC8F4F9700> @A.add
19

新式类继承顺序:D->B->C->A, 广度优先,从左到右。

事实上类中的_mro_属性(method resolution order)中定义了继承顺序,我们可以打印出来验证一下:

print(D.mro())
# 执行结果  ==========================================================================
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

参考资料

https://zhuanlan.zhihu.com/p/130404117

https://zhuanlan.zhihu.com/p/268136917

标签:__,15,self,add,面向对象,init,print,super,def
From: https://www.cnblogs.com/tian777/p/17517831.html

相关文章

  • Educational Codeforces Round 151 (Rated for Div. 2)(C,D)
    EducationalCodeforcesRound151(RatedforDiv.2)(C,D)C(dp,子序列自动机)C题目大意就就是给你一个字符串\(s\),还给出两个边界字符串\(l\)和\(r\),长度为\(m\),问我们是否可以构造满足一下条件的字符串\(1\),第\(i\)个字符必须在\(l_i\)和\(r_i\)的双闭区间里面\(2\),......
  • P3975 [TJOI2015] 弦论 题解
    一、题目描述:给你一个长度为$n$的字符串,字符串由$26$个小写字母组成,求第$k$大的字串。给定参数$t$:$t=0:\位置不同的相同字串只算一个。$$t=1:\位置不同的相同字串算作多个。$若字串数量不足$k$个,输出$-1$。数据范围:$1\le......
  • Educational Codeforces Round 151 (Rated for Div. 2) A~D
     A.ForbiddenInteger模拟:voidsolve(){intn,k,x;cin>>n>>k>>x;if(x!=1){cout<<"YES\n"<<n<<"\n";for(inti=1;i<=n;i++)cout<<"1"<<"\n"......
  • 15个下载量均过亿使用率超高的Python库
    今天给大家分享最近一年内PyPI上下载量最高的Python包。现在我们来看看这些包的作用,他们之间的关系,以及为什么如此流行。1.Urllib3:8.93亿次下载Urllib3是Python的HTTP客户端,它提供了许多Python标准库没有的功能。线程安全连接池客户端SSL/TLS验证使用multipart......
  • Educational Codeforces Round 151 (Rated for Div
    C.StrongPassword给定一个字符串\(s\),一个密码的长度\(m\),下界字符串\(l\)和上界字符串\(r\),上下界字符串长度均为\(m\),且字符只在0~9范围内,上界字符串的第\(i\)位非严格大于下界字符串的第\(i\)位,密码的第\(i\)位需要位于\([l_i,r_i]\)内。问是否存在一个密码不是\(......
  • 基于UDS的BootLoader上位机源代码的重写版本,该版本使用C#语言编写。该上位机源代码支
    基于UDS的BootLoader上位机源代码的重写版本,该版本使用C#语言编写。该上位机源代码支持ISO15765通信协议,并且兼容PeakCAN、ZJGCAN等多种CAN卡。此外,它还支持解析S-record格式的二进制文件基于UDS的BootLoader上位机源代码(C#)基于UDS的BootLoader上位机源代码,支持ISO15765通信,支持......
  • 老外最喜欢用的15款社交软件,不回邮件就去这里找他!
    外贸人不仅要懂得跟外国客户谈生意……私底下的问候、关心、聊天也必不可少。其实很多老外都不喜欢来回发邮件,他们大多数时间都是泡在社交软件上。如果能掌握外国客户常用的几款社交软件,并了解对方的喜好和生活习惯,就可以有更多的谈资和切入点引起对方的注意哦!下面贸小七就来介绍几......
  • AP8505高压同步整流 5V150mA非隔离电源ic
    深圳市三佛科技有限公司AP8505高压同步整流5V150mA非隔离电源icAP8505基于高压同步整流架构,集成PFM控制器以及500V高可靠性MOSFET,用于外部元器件极精简的小功率非隔离开关电源。AP8505无线门铃芯片内置500V高压启动,实现系统快速启动、超低待机功能。5V非隔离无线门铃芯片AP8505提......
  • 15分钟,3个亿!凭借复制粘贴,Azuki套现2万枚ETH?
       依托日漫风格起家的Azuki,一度被业内誉为“东方无聊猿”。作为NFT界的新星,Azuki的总销量曾轻松超过无聊猿和CryptoPunks等蓝筹项目。而酝酿一年之久的「AzukiElementals」新系列发售,却让社区破了大防。   根据官方公告,这个名为「AzukiElementals」的新系列跨越四个不同的......
  • Python面向对象之元类
    Python面向对象之元类【一】前言引入千万不要被所谓“元类是99%的python程序员不会用到的特性”这类的说辞吓住。因为每个中国人,都是天生的元类使用者我们引用太极的思想道生一,一生二,二生三,三生万物即我是谁?我从哪里来?我到哪里去?我们拿到Python中type就相当于我们......