对于面向对象的理解:
面向对象很符合我们人类的思维过程。比如说:当你自己需要一张床的时候,是不是需要用到木材,钉子,锤子等等。其实,我们所用的就是面向对象的思维过程,在这个过程中,我们需要用锤子砸钉子,那锤子不就是一个对象,钉子不也是一个对象吗?而锤子是用钢材料制作而成的可以抽象为一个类的属性,锤子可以砸钉子可以抽象为一个类的方法。接下可以进一步做定义,锤子是不是又可以分为大锤子、小锤子,钢制的锤子、胶纸锤子等等,但是锤子的形状是不变的吧,我们可以将符合锤子的形状的物品定义为锤子,将大锤子、小锤子等等继承锤子类,这样父类和子类的概念就出来了。
其实,面向对象的诞生就是为了降低耦合性,使编码更符合人类解决问题的思考过程。
一、面向对象有三大特点:
封装
继承
多态
1、封装
简单来说就是不能直接访问和改变类的属性。封装让类的使用时,起到更加安全的作用。
Python中没有像C++中 public 和 private 这些关键字来区别公有属性和私有属性。
Python是以属性命名方式来区分,如果在属性和方法名前面加了2个下划线’__’,则表明该属性和方法是私有权限,否则为公有权限。
2、继承
继承是一种创建新的类的方式,新创建的叫子类,继承的叫父类。子类可以使用父类的属性(特征、技能)继承的目的就是为了减少的冗余。
class grandFather():
print('我是爷爷')
class Parent(grandFather):
print('我是父类')
class SubClass(Parent):
print('我是子类')
sub = SubClass()
输出:
我是爷爷
我是父类
我是子类
注意:类在定义的时候就执行类体代码,执行顺序是从上到下
多继承
class Parent2():
print('我是第二个爹')
class Parent():
print('我是第一个爹')
class SubClass(Parent, Parent2):
print('我是子类')
#
# 结果:我是第二个爹
# 我是第一个爹
# 我是子类
注意:类在定义的时候就执行类体代码,执行顺序是从上到下
3、多态
只关心对象的实例方法是否同名,不关心对象所属的类型;对象所属的类之间,继承关系可有可无;多态的好处可以增加代码的外部调用灵活度,让代码更加通用,兼容性比较强;多态是调用方法的技巧,不会影响到类的内部设计。
class gradapa(object):
def __init__(self,money):
self.money = money
def p(self):
print("this is gradapa")
class father(gradapa):
def __init__(self,money,job):
super().__init__(money)
self.job = job
def p(self):
print("this is father,我重写了父类的方法")
class mother(gradapa):
def __init__(self, money, job):
super().__init__(money)
self.job = job
def p(self):
print("this is mother,我重写了父类的方法")
return 100
#定义一个函数,函数调用类中的p()方法
def fc(obj):
obj.p()
gradapa1 = gradapa(3000)
father1 = father(2000,"工人")
mother1 = mother(1000,"老师")
fc(gradapa1) #这里的多态性体现是向同一个函数,传递不同参数后,可以实现不同功能.
fc(father1)
print(fc(mother1))
===运行结果:===================================================================================
this is gradapa
this is father,我重写了父类的方法
this is mother,我重写了父类的方法
100
多态就是把各种类的相同的方法抽取出来。
小结:
1、init() 方法是设置对象属性,不在此方法下是雷属性。
2、str()方法是当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了__str__(self)方法,那么就会打印从在这个方法中 return 的数据
3、del_()方法是创建对象后,python解释器默认调用__init__()方法;当删除对象时,python解释器也会默认调用一个方法,这个方法为__del__()方法 del(对象) 删除对象
二、类属性和实例属性
类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本,这个和C++中类的静态成员变量有点类似。(static)
class People(object):
address = '山东' # 类属性
def __init__(self):
self.name = 'xiaowang' # 实例属性
self.age = 20 # 实例属性
p = People()
p.age = 12 # 实例属性
print(p.address) # 正确
print(p.name) # 正确
print(p.age) # 正确
print(People.address) # 正确
print(People.name) # 错误
print(People.age) # 错误
类属性就是公有的。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。
三、静态方法和类方法
1,类方法:
是类对象所拥有的方法,需要用修饰器@classmethod来标识其为类方法
对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数(当然可以用其他名称的变量作为其第一个参数,但是大部分人都习惯以’cls’作为第一个参数的名字,就最好用’cls’了),能够通过实例对象和类对象去访问。
class People(object):
country = 'china'
#类方法,用classmethod来进行修饰
@classmethod
def get_country(cls):
return cls.country
@classmethod
def set_country(cls,country):
cls.country = country
p = People()
print(p.get_country()) #可以用过实例对象访问
print(People.get_country()) #可以通过类访问
p.set_country("japan")
print(p.get_country())
print(People.get_country())
结果:
china
china
japan
japan
2,静态方法
需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数,可以通过对象和类来访问。
class People(object):
country = 'china'
@staticmethod
#静态方法
def get_country():
return People.country
p = People()
# 通过对象访问静态方法
print(p.get_country())
# 通过类访问静态方法
print(People.get_country())
结果:
china
china