Python——类、面向对象,封装 继承 多态
https://www.jianshu.com/u/d959ac37cdde
1-1F605141A3Q0.png面向过程:根据业务逻辑从上到下写代码
面向对象:将数据与函数绑定到一起,进行封装,这样能够更快速的开发程序,减少了重复代码的重写过程
类
人以类聚 物以群分。
具有相似内部状态和运动规律的实体的集合(或统称为抽象)。
具有相同属性和行为事物的统称
类是抽象的,在使用的时候通常会找到这个类的一个具体的存在,使用这个具体的存在。一个类可以找到多个对象
在Python中编写类的方式如下:
class Dog():
'''创建小狗的类'''
def __init__(self,name,age):
self.name = name
self.age = age
'''动作方法 play'''
def sit(self):
print('狗在玩')
方法init()
init()是一个特殊的方法,每当根据类创建类的实例时,Python都会自动运行这个方法。在这个方法中开头和末尾各有两个下划线。
避免Python默认方法与普通方法发生名称冲突。
init()定义中我们传递了三个参数:self、name和age。这个初始化方法中self是必须的。而且还必须位于其他的形参前面。每个与类相关联的方法调用都自动传递实参self,它是一个指向实例本身的引用。让实例能够访问类中的属性和方法
在init()方法中定义的两个变量都有前缀self。以self为前缀的变量都可供类中的所有方法使用。
init()没有并没有显式地包含return语句,但Python自动返回类对象的实例。
- init_()方法,在创建一个对象时默认被调用,不需要手动调用
- init(self)中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么init(self)中出了self作为第一个形参外还需要2个形参,例
-
init(self,x,y)
init(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递进去*
Python3.0创建类的方法
- 在Python3.0中创建类
class ClassName(Object):
pass
根据类创建实例
my_dog = Dog()
my_dog.play()
为属性指定默认值
类中的每个属性指定默认值。
3 class CarPro:
4 def __init__(self):
5 self.t=0
6 self.info='铁皮'
7 self.SideDishes=[]
8 def __str__(self):
9 a=''
10 for i in self.SideDishes:
11 a+=i+','
12 a=a.strip(',')
13 return '现在加工的是%s,加工了%d分钟'%(self.info,self.t)
14
15 def CarProduct(self,t1):
16 self.t+=t1
17 if self.t>=10:
18 self.info='汽车产生了'
19 elif self.t>=8:
20 self.info='汽车各个部件喷涂'
21 elif self.t>=6:
22 self.info='汽车各个部件涂胶'
23 elif self.t>=5:
24 self.info='汽车各个部位点焊,弧焊,铆焊'
25 else:
26 self.info='一堆铁皮'
类的继承
在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物;同理,波斯猫和巴厘猫都继承自猫,而沙皮狗和斑点狗都继承足够。
- 定义子类时,必须在括号内指定父类的名称
- 在创建子类的实例时,Python首先需要给父类的所有属性赋值。
- 创建子类时,父类必须包含在当前文件中,且位于子类前面。
- 子类中可以使用super()代表父类的引用。
class Cat(object):
def __init__(self, name, color="白色"):
self.name = name
self.color = color
def run(self):
print("%s--在跑"%self.name)
# 定义一个子类,继承Cat类如下:
class Bosi(Cat):
def setNewName(self, newName):
self.name = newName
def eat(self):
print("%s--在吃"%self.name)
bs = Bosi("印度猫")
print('bs的名字为:%s'%bs.name)
print('bs的颜色为:%s'%bs.color)
bs.eat()
bs.setNewName('波斯')
bs.run()
类——object
每一个python类都隐含了一个超类:object,这个类是一个非常简单的定义,这个类几乎不做任何事情。
重写、调用父类方法
- 所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
看几个栗子
class Cat(object):
def sayHello(self):
print("halou-----1")
class Bosi(Cat):
def sayHello(self):
print("halou-----2")
bosi = Bosi()
bosi.sayHello()
>>>
<__main__.son object at 0x101a45908>
class Cat(object):
def __init__(self,name):
self.name = name
self.color = 'yellow'
class Bosi(Cat):
def __init__(self,name):
# 调用父类的__init__方法1(python2)
#Cat.__init__(self,name)
# 调用父类的__init__方法2
#super(Bosi,self).__init__(name)
# 调用父类的__init__方法3
super().__init__(name)
def getName(self):
return self.name
bosi = Bosi('xiaohua')
print(bosi.name)
print(bosi.color)
多继承
Python支持多继承,我们知道子类会继承父类中的属性和方法。python中需要继承多个类的时候,使用如下的格式
class 子类(父类1,父类2):
pass
那么当多个父类都含有相同的方法,会如何执行呢?
class father1:
def say(self,args):
print(args+'father1')
class father2:
def say(self,args):
print(args+'father2')
class son(father1,father2):
pass
s = son()
s.say('it say something')
>>>
it say somethingfather1
可以看到,python会执行第一个父类中的相关方法
142800ycssa7s7m00aac2t.png
我们用图解来解释一下执行顺序
# 定义一个父类
class A:
def printA(self):
print('----A----')
# 定义一个父类
class B:
def printB(self):
print('----B----')
# 定义一个子类,继承自A、B
class C(A,B):
def printC(self):
print('----C----')
obj_C = C()
obj_C.printA()
obj_C.printB()
python中是可以多继承的
父类中的方法、属性,子类会继承
我们根据执行结果,可以看到程序会现在子类中查找要执行的方法和函数,然后会在第一个父类中寻找如果没有找到,会在第二个父类中寻找。如果也没有找到会去父类的公共基类找。
程序的执行顺序是 1 2 3
私有化
- 如果有一个对象,当需要对其进行修改属性时,有2种方法
对象名.属性名 = 数据 ---->直接修改
对象名.方法名() ---->间接修改 - 为了更好的保存属性安全,即不能随意修改,一般的处理方式为
将属性定义为私有属性
添加一个可以调用的方法,供调用
静态方法和类方法
是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以’cls’作为第一个参数的名字,就最好用’cls’了),能够通过实例对象和类对象去访问。
- 静态字段的创建
class People(object):
country = 'china'
@staticmethod
#静态方法
def getCountry():
return People.country
print (People.getCountry())
类方法
- 调用get方法
test = duck('test123')
print(test.get_name)
- 调用setter方法
test = duck('test123')
test.set_name = '123test'
print(test.get_name)
使用名称重整保护私有特性
在前面的Duck例子中,如果直接访问hidden_name还是可以看到对应属性的值。Python对那些需要可以隐藏在类内部的特性有自己的命名规范:由连续的两个下划线开头(__)
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
p = People()
print (p.getCountry()) #可以用过实例对象引用
print (People.getCountry()) #可以通过类对象引用
类方法还有一个用途就是可以对类属性进行修改:
对于父类的方法,只要它不符合子类的调用行为,都可以对其重写。
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def getCountry(cls):
return cls.country
@classmethod
def setCountry(cls,country):
cls.country = country
p = People()
print (p.getCountry()) #可以用过实例对象引用
print (People.getCountry()) #可以通过类对象引用
p.setCountry('japan')
print (p.getCountry())
print (People.getCountry())
结果显示在用类方法对类属性修改之后,通过类对象和实例对象访问都发生了改变
模块
from part2.classdemo.car import Car
import会让Python打开模块car并导入其中的Car类
- 在一个模块中存储多个类
- 从一个模块导入多个类
可根据需要在程序文件中导入任意数量的类。从一个模块中导入多个类时,用逗号分隔导入的个各类。导入必要的类后,就可以根据需要创建每个类的任意数量的实例
from part2.classdemo.car import Car, ElectricCar
模块中的all
-
被导入的模块,最上边 加入 all = ['one' , 'two'] #添加的方法名称对应的方法。
在from test import * 导入的情况下, all 所指明的方法会被导入可以使用;其他的不会被*号导入; -
通过在文件开头
用 all 指定可以被 from……import* 导入的方法
网友评论