一、静态属性

静态属性相当于数据属性。

用@property语法糖装饰器将类的函数属性变成可以不用加括号直接的类似数据属性。

可以封装逻辑,让用户感觉是在调用一个普通的数据属性。

例子:

classRoom:def __init__(self,name,length,width,heigh):

self.name=name

self.length=length

self.width=width

self.heigh=heigh

@property#通过使用property语法糖装饰器,使类的函数属性返回类似数据属性,不用使用括号。

defcacl_area(self):return self.length*self.width

r1= Room("nick",20,30,10)print(r1.cacl_area)

二、类方法

需求:类不通过实例(对象)直接调用类的函数属性。

类无法直接调用自己的函数属性,需要借助实例对象。

例子:

classRoom:def __init__(self,name,length,width,heigh):

self.name=name

self.length=length

self.width=width

self.heigh=heigh

​defcacl_area(self):return self.length*self.width

​deftell_info(self):print("-----")

Room.tell_info()#这样直接用类调用函数属性会出错,需要实例对象

r1=Room("nick",10,10,10)

r1.tell_info()

需要用@classmethod ,将函数做成类方法,执行类方法时,自动将调用该方法的类复制给cls;

例子:

classRoom:def __init__(self,name,length,width,heigh):

self.name=name

self.length=length

self.width=width

self.heigh=heigh

​defcacl_area(self):return self.length*self.width

@classmethoddeftell_info(cls,msg):print(cls)print("-----",msg)

Room.tell_info("hello") #相当于Room.tell_info(Room,"hello"),classmethod自动将类传入了

三、静态方法

用@staticmethod 语法糖实现,不和具体的实例对象进行绑定,类可以调用实例也可以调用

例子:

classRoom:def __init__(self,name,length,width,heigh):

self.name=name

self.length=length

self.width=width

self.heigh=heigh

​defcacl_area(self):return self.length*self.width

@staticmethoddeftest(a,b,c):print(a,b,c)

Room.test("hello","world","!!!") #静态方法类可以调用,实例也可以调用

r1 = Room("nick",20,30,10)

r1.test("nick","hello","!!!")

输出结果:

hello world !!!

nick hello !!!

静态方法只是名义上归属类管理,不能使用类变量和实例变量,是类的工具包。

补充:

绑定方法说明:

♦绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入)

♦绑定到对象的方法:没有被任何装饰器装饰的方法。

♦绑定给类的方法(classmethod)

♦非绑定方法:用staticmethod装饰器装饰的方法:不与类或对象绑定,类和对象都可以调用,但是没有自动传值。

四、组合

组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

用途:

1、不同的类做关联

2、不同的类组合成大的整体。

例子1:

classSchool:def __init__(self,name,addr,type):

self.name=name

self.addr=addr

self.type=type

​defenrol_students(self):print("%s正在招生"%self.name)

​defexam(self):print("%s正在考试"%self.name)

​classCourse:

​def __init__(self,name,price,period,school):

self.name=name

self.price=price

self.period=period

self.school=school

s1= School("清华","北京","公立")

s2= School("北大","北京","公立")

school_dic={"1":s1,"2":s2

}

msg= """请选择学校

1、清华

2、北大

​"""

whileTrue:print(msg)

school_choice= input(">>>:").strip()

name= input("课程名:").strip()

price= input("课程费用:").strip()

period= input("课程周期:").strip()

school_obj=school_dic[school_choice]

c1= Course(name,price,period,school_obj) #直接传入学校的对象,不同类之间建立了关联

print("%s属于%s"%(c1.name,c1.school.name))

例子2:

classHead():pass​

​classTrunk:pass​

​classHand():pass​

​classFoot():pass​

​classPeople():def __init__(self, name, age, gerder, ):

self.name=name

self.age=age

self.gerder=gerder

self.head= Head() #人的头继承了head类这个类得实例,这里是一个对象

self.trunk =Trunk()

self.hand=Hand()

self.foot=Foot()

p1= People("nick", '18', "man")print(p1.__dict__) #打印得到一个属性head ->>> key的值对应的head实例

例子3:

rom math importpi

​classCircle:def __init__(self,radius):

self.radius=radius

​defcacl_area(self):print("圆的面积是%s"%(pi*self.radius*self.radius))return pi*self.radius*self.radius

​classRing:def __init__(self,outside_radius,inside_radius):

self.outside_circle= Circle(outside_radius) #获取外圈圆的对象

self.inside_circle = Circle(inside_radius) #获取内圈圆的对象

​defarea(self):

ring_area= self.outside_circle.cacl_area() -self.inside_circle.cacl_area()print("圆环的面积是%s"%ring_area)

r1= Ring(10,8)

r1.area()

五、继承

什么是继承?

继承指的是类与类之间的关系,是一种什么“是”什么的关系,继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称为基类或超类,新建的类称为派生类或子类。

子类会“”遗传”父类的属性,从而解决代码重用问题。

例子1:

classParent_class:

money= 10

def __init__(self,name):

self.name=name

​defmake_money(self):print("make good money")

​classSub_class(Parent_class):pass​

s1= Sub_class("nick") #这里需要传入一个参数,虽然子类没有默认的__init__方法,子类找不到去父类找,父类需要一个参数

print(s1.money) #这里直接调用父类的数据属性

s1.make_money() #调用父类的函数属性

分析:子类继承了父类的数据属性和函数属性

派生

子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

例子2:

classParent_class:

money= 10

def __init__(self,name):

self.name=name

​defmake_money(self):print("make good money")

​classSub_class(Parent_class):

money= 10000​

s1= Sub_class("nick")print(s1.money) #这里子类有自己的与父类同名的属性,从子类的属性开始找,自己有就用自己的数据,不再用父类的数据

print(Parent_class.money) #父类的属性任然存在,而不是被子类的同名属性覆盖了

s1.make_money() #调用父类的函数属性

分析:子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。父类的属性任然存在。

在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能,应该是用调用普通函数的方式,即:类名.func(),此时就与调用普通函数无异了,因此即便是self参数也要为其传值。

classParent_class1:

money= 10

def __init__(self,name):

self.name=name

​defmake_money(self):print("from Parent_class1")print("make good money")

​classSub_class(Parent_class1,):

money= 10000​def make_money(self): #在自己这里定义新的make_money,不再使用父类的make_money,且不会影响父类

Parent_class1.make_money(self) #如果想调用父类的同名函数属性,这里要自己手写self。

print("from Sub_class")

s1= Sub_class("nick")

s1.make_money()

属性查找

属性引用查找,会先从对象中找,然后去类中找,然后再去父类中找...直到最顶级的父类。

例子:

classParent_class1:deff1(self):print("from Parent_class f1")

​deff2(self):

self.f1()print("from Parent_class f2")

​classSub_class(Parent_class1,):deff1(self):print("from Sub_class")

s1=Sub_class()

s1.f2()

输出结果:

fromSub_classfrom Parent_class f2

分析:对象s1自己的类本身没有f2()函数属性,到父类找,找到了执行self.f1(),这里的self是对象s1,所以s1.f1()函数属性执行结果是输出from Sub_class,然后执行print("from Parent_class f2")输出from Parent_class f2

查看继承

用__base__、__bases__方法

classParent_class1:

money= 10

def __init__(self,name):

self.name=name

​defmake_money(self):print("make good money")

​classParent_class2:pass​classSub_class(Parent_class1,Parent_class2):

money= 10000​

​print(Sub_class.__base__)print(Sub_class.__bases__)

输出结果:

(, )

分析:

#__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类

什么时候用继承?

当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好。

通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。

比如老师是人,学生是人。

当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好。

用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3。

六、接口继承和统一化设计

继承同时具有两种含义:

继承基类的方法,并且做出自己的改变或者扩展(解决代码重用问题)。

声明某个子类兼容于某基类,定义一个接口类,子类继承接口类,并且实现接口中定义的方法。

继承的第二种含义非常重要。它又叫“接口继承”。

封装:封装的意义,在于明确标识出允许外部使用的所有成员函数和数据项,或者叫接口。

真正的封装是,经过深入的思考,做出良好的抽象,给出“完整且最小”的接口,并使得内部细节可以对外透明(注意:对外透明的意思是,外部调用者可以顺利的得到自己想要的任何功能,完全意识不到内部细节的存在。

总结

(1)实践中继承的第一种含义意义并不是很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。

(2)继承的第二种含义非常重要。接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”,这在程序设计上叫做归一化。

归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕。

​ 接口提取了一群类共同的函数,可以把接口当做一个函数的集合。然后让子类去实现接口中的函数。归一化,就是只要是基于同一个接口实现的类,那么所有的这些类产生的对象在使用时,从用法上来说都一样。归一化,让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。

抽象类

抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化。

如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。

比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。

​ 从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。

抽象类与接口

抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

*抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计*

接口继承的使用例子(抽象类)

importabcclass All_file(metaclass=abc.ABCMeta): #接口类(基类),接口类的方法不需要具体实现,也不需要实例化

@abc.abstractmethod#引入第三方模块abc,调用abc下的abstractmethod,强制子类下必须有read方法

defread(self):pass​

@abc.abstractmethod#强制子类下必须有write方法

defwrite(self):pass​

​classText_file(All_file):defread(self):print("from text-file read")

​defwrite(self):print("from text-file write")

​classDisk(All_file):defread(self):print("from disk read")

​defwrite(self):print("from disk write")

​classCdrom(All_file):defread(self):print("from cdrom read")

​defwrite(self):print("from cdrom write")

f1=Disk()

f1.read()

七、继承顺序

经典类与新式类

在python2中,新式类基类继承object类,经典类不继承任何类

\

默认都是经典类,只有显式继承了object才是新式类,即:

class Person(object):pass 新式类写法

class Person():pass 经典类写法

class Person:pass 经典类写

在Python 3.x中取消了经典类,默认都是新式类,并且不必显式的继承object

class Person(object):pass

class Person():pass

class Person:pass

三种写法并无区别

继承顺序

Python中子类可以同时继承多个父类,如A(B,C,D)

如果继承关系为非菱形结构,则会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性。

深度优先和广度优先

继承关系为菱形结构,那么属性的查找方式有两种,分别是:深度优先和广度优先。

例子:

classG:deftest(self):print("from G")

​classF(G):deftest(self):print("from F")

​classE(G):deftest(self):print("from E")

​classD(G):deftest(self):print("from D")

​classC(F):deftest(self):print("from C")

​classB(E):deftest(self):print("from B")pass​classA(B,C,D):deftest(self):print("from A")#pass

c1=A()

c1.test()

​#python3环境中,新式类继承的寻找的顺序是A-B-E-C-F-D-G#在python2环境中,这个为经典类,继承寻找的顺序为A-B-E-G-C-F-D#python3中统一都是新式类,全部按照广度优先继承#pyhon2中才分新式类与经典类

继承原理

对于定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表。

为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。

C3线性化算法实际上就是合并所有父类的MRO列表并遵循如下三条准则:

子类会先于父类被检查

多个父类会根据它们在列表中的顺序被检查

如果对下一个类存在两个合法的选择,选择第一个父类

例子(python3)

classG:deftest(self):print("from G")

​classF(G):deftest(self):print("from F")

​classE(G):deftest(self):print("from E")

​classD(G):deftest(self):print("from D")

​classC(F):deftest(self):print("from C")

​classB(E):deftest(self):print("from B")pass​classA(B,C,D):deftest(self):print("from A")

​print(A.mro())

输出结果:

[, , , , , , , ]

分析:#python2中的新式类也和python3一样,都有mro方法,python2中经典类没有mro方法。

八、子类调用父类方法

在子类派生出的新方法中,往往需要重用父类的方法,我们有两种方式实现

第一种方式:直接调用

指名道姓,即父类名.父类方法()

class Vehicle: #定义父类

​def __init__(self,name,speed,power):

self.name=name

self.speed=speed

self.power=power

​defrun(self):print("running !")

​class Subway(Vehicle): #定义子类

​def __init__(self,name,speed,power,line):

Vehicle.__init__(self,name,speed,power) #这里调用父类的构造方法,直接用父类名.构造方法名(),

#需要自己传入self和其他父类的参数

self.line =line

​defrun(self):

Vehicle.run(self)#这里调用父类的run()方法也是采用父类名.父类方法()的方式,也是需要自己传入self

print("%s %s号线开动了"%(self.name,self.line))

s= Subway("深圳地铁","70km/h","电力",1)

s.run()

第二种方式:super()

用super().父类方法(),这种方式不用写父类的名字,不用再传入self这个参数了。

class Vehicle: #定义父类

​def __init__(self,name,speed,power):

self.name=name

self.speed=speed

self.power=power

​defrun(self):print("running !")

​class Subway(Vehicle): #定义子类

​def __init__(self,name,speed,power,line):

super().__init__(name,speed,power) #这里用super().父类的方法名调用父类的方法,这种方式不用传入self参数

self.line =line

​defrun(self):

super().run()#这里调用父类的run()方法也是采用super().父类方法()的方式,不需要自己传入self参数

print("%s %s号线开动了"%(self.name,self.line))

s= Subway("深圳地铁","70km/h","电力",1)

s.run()

python静态属性和静态方法_Python之路系列:面向对象初级:静态属性、静态方法、类方法...相关推荐

  1. python创建对象的格式为_Python入门基础学习(面向对象)

    python基础学习笔记(四) 面向对象的三个基本特征: 封装:把客观事物抽象并封装成对象,即将属性,方法和事件等集合在一个整体内 继承:允许使用现有类的功能并在无须重新改写原来的类情况下,对这些功能 ...

  2. python类和对象介绍_Python开发基础-Day17面向对象编程介绍、类和对象

    面向对象变成介绍 面向过程编程 核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西.主要应用在一旦完成很少修改的地方,如linux ...

  3. python中静态变量和静态方法_python类和函数中使用静态变量的方法

    本文实例讲述了python类和函数中使用静态变量的方法.分享给大家供大家参考.具体分析如下: 在python的类和函数(包括λ方法)中使用静态变量似乎是件不可能[Nothing is impossib ...

  4. python高级属性 用法 编程_python高级编程之面向对象高级编程

    1 面向对象编程 面向对象这节比较简单,就稍微总结几个特殊的点. 特殊方法__init__前后分别有两个下划线,__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init ...

  5. python变量名称引用变量_Python:按变量名引用对象属性?

    我在用Python编写棋盘游戏专卖版.垄断有三种类型的土地,玩家可以购买:财产(如木板路),铁路和公用事业.房产的购买价格和租金在6种情况下都是可变的(0-4套房子或一家酒店).铁路和公用事业有一个固 ...

  6. python模板引擎传迭代器_python之路 模块,序列化,迭代器,生成器

    一.模块 1.模块简介 模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py.模块可以被别的程序引入,以使用该模块中的函数等功能.这也是使用python标准库的方法. 类似于函数式编程和面向过 ...

  7. python连接linux堡垒机_Python之路:堡垒机实例以及数据库操作

    一.堡垒机前戏 开发堡垒机之前,先学习Python的paramiko模块,该模块基于SSH用于连接远程服务器并执行相关操作. SSHClient 用于连接远程服务器并执行基本命令 基于用户名密码连接: ...

  8. python tkinter库函数详解_Python连载60-Tkinter布局、按钮以及属性详解

    一.Tkinter​ 1.组件的大致使用步骤 (1)创建总面板 (2)创建面板上的各种组件: i.指定组件的父组件,即依附关系:ii.利用相应的属性对组件进行设置:iii.给组件安排布局. (3)同步 ...

  9. python将空格变成换行_python之路(2)

    变量 通过桌面的开始菜单,打开python的IDLE 打开IDLE后,新建一个文件 保存一下 现在就可以开始我们的学习了 在下图中,被单引号围起来的  '123'  表示的是字符串,因为是由多个字符组 ...

最新文章

  1. C#委托及事件 详解(讲得比较透彻)
  2. 分布式与人工智能课程(part10)--图像库的基本使用
  3. cas后端返回html直接跳转,CAS验证成功后不能跳转到登陆成功的主页面解决办法...
  4. C++网络编程快速入门(二):Linux下使用select演示简单服务端程序
  5. Android Studio Gradle构建脚本
  6. 【附源码】为了帮助程序员谈恋爱,我做了这个APP
  7. windows环境的rabbitmq安装与启动
  8. 前台收银系统授权服务器未开启,佳为软件操作大全 佳为收银系统
  9. IBM P750 AIX机器根目录空间满问题解决办法
  10. 金蝶连服务器显示演示版,金蝶正版和金蝶演示版的区别
  11. PHP容器--Pimple运行流程浅析
  12. 云原生安全之容器级网站防篡改
  13. Epson机械手简单实例编程
  14. 【数论】君と彼女の恋
  15. Wine零知识学习1 —— 介绍
  16. Neural-Motifs 源码解读(3):RelModel类
  17. Linux-2 文件管理(vi 和vim)
  18. 智能客服赛道:网易七鱼、微洱科技打法迥异
  19. 联通软件研究院笔试题1
  20. 电脑wifi通过中继器上网频繁掉线问题分析及问题解决方案(DHCP NAK)

热门文章

  1. 记录C语言学习【单个按键之长按+短按】
  2. Android外接midi设备的录音
  3. 人人转联盟官网?人人转联盟是真的吗?人人转联盟能赚钱吗?
  4. Unity开发win10软件系列问题6: unity调用 win10 虚拟键盘tabtip.exe
  5. (二)ArcGIS JS 加载动态地图服务
  6. (实测可用)STM32CubeMX教程-STM32L431RCT6开发板(定时器Timer2)
  7. 工作流Activiti初体验—流程撤回【二】
  8. 字符流的相关概念和相关方法的使用、IO异常的处理以及Properties属性集
  9. 对卡巴斯基发现的一个将shellcode写入evenlog的植入物的复现
  10. c语言access码大小写A转换,字母大小写互相转换 ASCII码转化符号问题