python学习笔记之---面向对象的三大特性

面向对象的三个特征:封装,继承,多态
封装:把数据和操作数据的方法,用类来实现。保证数据的安全性
继承:子类可以使用父类的共有属性和共有方法。
多态:参数类型用基类声明,执行的时候会根据传入的对象
      去执行相应的方法,具有不同的效果。
 

封装
将对象的数据与操作数据的方法相结合,通过方法将对象的数据与实现细节保护起来,就称为封装。
封装可以让调用者不用关心对象是如何构建的而直接进行使用。
#coding=utf-8
class Animal(object):
    def __init__(self, name):
    #构造方法一个对象创建后会立即调用此方法
        self.Name = name
        print (self.Name)

    def accessibleMethod(self):
    #绑定方法对外公开
        print ("I have a self! current name is:")
        print (self.Name)
        print ("the secret message is:")
        self.__inaccessible()

    def __inaccessible(self):
    #私有方法对外不公开以双下划线开头
        print ("U cannot see me...")

    @staticmethod
    def staticMethod():
    # self.accessibleMethod() #在静态方法中无法
    #直接调用实例方法直接抛出NameError异常
        print("this is a static method")

    def setName(self,name): #访问器函数
        print ("setName:")
        self.Name=name

    def getName(self): #访问器函数
        print ("getName:")
        return self.Name

a = Animal("learns")
print (a.getName)
a.setName("sr")
print ("new name:",a.getName())
a.staticMethod()
a.accessibleMethod()

E:>py -3 a.py
learns
<bound method Animal.getName of <__main__.Animal object at 0x0000000003ED6160>>
setName:
getName:
new name: sr
this is a static method
I have a self! current name is:
sr
the secret message is:
U cannot see me...

 
 
 

继承
#单继承:子类具备所有父类的共有变量和共有方法(除私有的)
如果子类没有定义__init__构造方法,会自动调用父类的。
好处:站在老爸的肩膀上,增加属性,增加方法
      在原有的基础上进行扩展。
class Person:
    count = 0 #类变量
    nation = "中国"
 
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
        Person.count +=1
        print("创建了一个新的人")
 
    def get_name(self):#实例方法,必须要实例化
        return self.name
 
class ChinaPerson(Person):
      #如果子类没有定义__init__构造方法
      #会自动调用父类的。
    def __init__(self,name,gender):
        Person.__init__(self,name,gender)  #调用父类的构造函数:类名+构造函数
 
    def get_gender(self):
        return self.gender
 
cp = ChinaPerson("吴老师","")
print(cp.count)
print(cp.name)
print(cp.gender)
print(cp.get_name())
C:UsersdellDesktop练习6>py -3 0616.py
创建了一个新的人
1
吴老师
吴老师
 
 
 
#多继承: 在括号里面写上多个基类(父类)
子类的构造函数,如果没有实现,则调用第一个基类的构造函数。
class Person:
    count = 0 #类变量
    nation = "中国"
 
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
        Person.count +=1
        print("创建了一个新的人")
 
    def get_name(self):#实例方法,必须要实例化
        return self.name
 
class Bird:
 
    def __init__(self,color):
        print("a bird is birthed!")
        self.color = color
 
    def fly(self):
        print("I can fly in the sky!")
 
class ChinaBirdPerson(Person,Bird):  #括号里写上多个基类
      #如果子类没有定义__init__构造方法
      #会自动调用父类的。
    def __init__(self,name,gender,color):
        Person.__init__(self,name,gender)  #基类的两个构造方法都要调用,才能使用各自类的变量
        Bird.__init__(self,color)
 
    def get_gender(self):
        return self.gender
 
cp = ChinaBirdPerson("吴老师","","红色")
print(cp.color)
print(cp.get_name()) #继承了Person类的方法
print(cp.fly()) #继承了Bird类的方法
C:UsersdellDesktop练习6>py -3 0616.py
创建了一个新的人
a bird is birthed!
红色
吴老师
I can fly in the sky!
None
 
 
#多继承,当继承的类存在同名的方法,调用时先执行左边的类Person,如果左边没有时会找右边类的方法,
实例1:
class Person:
    count = 0 #类变量
    nation = "中国"
 
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
        Person.count +=1def get_name(self):#实例方法,必须要实例化
        return self.name
    
 
class Bird:
 
    def __init__(self,color):
        self.color = color
 
    def fly(self):
        print("I can fly in the sky!")
 
    def get_name(self):#实例方法,必须要实例化
        return "bird has no name"
 
class ChinaBirdPerson(Person,Bird):
      #如果子类没有定义__init__构造方法
      #会自动调用父类的。
    def __init__(self,name,gender,color):
        Person.__init__(self,name,gender)
        Bird.__init__(self,color)
 
    def get_gender(self):
        return self.gender
 
cp = ChinaBirdPerson("吴老师","","红色")
print(cp.get_name())
E:>py -3 a.py
吴老师
 
实例2:(Person类里没有get_name方法,会调用Bird类的get_name方法)
class Person:
    count = 0 #类变量
    nation = "中国"


    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
        Person.count +=1


class Bird:


    def __init__(self,color):
        self.color = color


    def fly(self):
        print("I can fly in the sky!")


    def get_name(self):#实例方法,必须要实例化
        return "bird has no name"


class ChinaBirdPerson(Person,Bird):
      #如果子类没有定义__init__构造方法
      #会自动调用父类的。
    def __init__(self,name,gender,color):
        Person.__init__(self,name,gender)
        Bird.__init__(self,color)


    def get_gender(self):
        return self.gender


cp = ChinaBirdPerson("吴老师","","红色")
print(cp.get_name())
E:>py -3 a.py
bird has no name
 
 
#python3多继承情况下找同名方法的时候,按照深度优先原则查找
从父类、爷爷类去查找方法,叫做深度优先
从多继承的同级类去查找方法,叫做广度优先
class P:
    def get_name(self):
        return "P name!"    
    pass
 
class Person(P):
    count = 0 #类变量
    nation = "中国"
 
    def __init__(self,name,gender):
        self.name = name
        self.gender = gender
        Person.count +=1
        print("创建了一个新的人")
 
    
 
class Bird:
 
    def __init__(self,color):
        print("a bird is birthed!")
        self.color = color
 
    def fly(self):
        print("I can fly in the sky!")
 
    def get_name(self):#实例方法,必须要实例化
        return "bird has no name"
 
class ChinaBirdPerson(Person,Bird):
      #如果子类没有定义__init__构造方法
      #会自动调用父类的。
    def __init__(self,name,gender):
        Person.__init__(self,name,gender)
        #Bird.__init__(self,color)
 
    def get_gender(self):
        return self.gender
 
cp = ChinaBirdPerson("吴老师","")
print(cp.get_name())
C:UsersdellDesktop练习6>py -3 0616.py
创建了一个新的人
P name!
 p  -->get_name(爷爷类)
       Person(父类)                Bird-->get_name(父类)
          ChinaBirdPerson(孙类)
 
cp.get_name()
 
 
 

多态
多态意味着可以对不同的对象使用同样的操作,但它们可能会以多种形态呈现出结果。
在Python中,任何不知道对象到底是什么类型,但又需要对象做点什么的时候,都会用到多态。

实例:

class Mobile():
    def get_country(self):
        pass

class HuaWei(Mobile):
    def get_country(self):
        print('China')

class Iphone(Mobile):
    def talk(self):
        print('America')

class SanXing(Mobile):
    def get_country(self):
        print('Korea')

#Python的多态性是指:在不考虑实例类型的情况下使用实例,也就是说不同类型的实例有相同的调用方法。
#HuaWei、Iphone、SanXing都有get_country方法,我们可以定义一个统一的接口来实现:
def func(obj):
    obj.get_country()  #多态一定会调用实例的方法


print(func(HuaWei()))  #调用HuaWei的实例方法
print(func(Iphone()))
print(func(SanXing()))

E:>py -3 a.py
China
None
None
Korea
None

 
工厂模式与多态的区别?例子:
def cook_factory(food):
    return food()  #工厂函数,只返回实例,不做调用
    food().getData()#调用了实例的方法,多态
 #方法多态:
#coding=utf-8
class calculator:
    def count(self,args):
        return 1
calc=calculator()
#自定义类型

from random import choice
#obj是随机返回的类型不确定
obj=choice(['hello,world',[1,2,3],calc])
print(obj)
print(type(obj))
print(obj.count('a')) #方法多态

第一次执行程序:

E:>py -3 a.py
hello,world
<class 'str'>
0

第二次执行程序:

E:>py -3 a.py
[1, 2, 3]
<class 'list'>
0

呈现结果:程序不变每次执行结果不同。
 
 
#多态---“鸭子类型”
#coding=utf-8
class Duck(object):
    def quack(self):
        print ("Quaaaaaack!")
    def feathers(self):
        print ("The duck has white and gray feathers.")

class Person(object):
    def quack(self):
        print ("The person imitates a duck.")
    def feathers(self):
        print ("The person takes a feather from the ground and shows it.")

def in_the_forest(duck):
        duck.quack()
        duck.feathers()

def game():
    donald = Duck()
    john = Person()
    in_the_forest(donald)
    in_the_forest(john)

game()

E:>py -3 a.py
Quaaaaaack!
The duck has white and gray feathers.
The person imitates a duck.
The person takes a feather from the ground and shows it.

就in_the_forest函数而言,参数对象是一个鸭子类型,它实现了方法多态。
但是实际上我们知道,从严格的抽象来讲,Person类型和Duck完全风马牛不相及

 
 #运算符多态
#coding=utf-8
def add(x,y):
    return x+y

print (add(1,2)) #输出3)
print (add("hello,","world") )#输出hello,world
print (add(1,"abc")) #将抛出异常 TypeError,不同类型不能相加'

E:>py -3 a.py
3
hello,world
Traceback (most recent call last):
File "a.py", line 7, in <module>
print (add(1,"abc")) #将抛出异常 TypeError,不同类型不能相加'
File "a.py", line 3, in add
return x+y
TypeError: unsupported operand type(s) for +: 'int' and 'str'

Python的加法运算符是”多态“的,理论上,我们实现的add方法支持任意支持加法的对象,
但是我们不用关心两个参数x和y具体是什么类型。

 
原文地址:https://www.cnblogs.com/wenm1128/p/11716543.html