python面向对象

面向对象编程OOP是一种编程思想。面向对象编程将对象作为程序的基本单元,一个对象包括了对象的数据(属性)和操作对象的函数(方法)。面向过程的编程计算机程序看做一系列命令集合,即函数的顺序执行。故函数是面向过程程序设计的基本单元。

1. 类

python将所有数据类型视为对象。我们可以自定义对象。类是一个抽象的概念,是一系列具有相同属性和方法的对象的集合。实例是一个具体的对象。 故面向对象的设计思想是抽象出类(class),根据类创建实例(instance)。

1.1 类和实例
  • 类定义:使用class关键字定义类

    • class_name:类名,通常首字母大写
    • object:表示继承自那个类,最终都会继承object类
  • 创建实例(实例化对象):instance_name = class_name()

# 类定义
class Message(object):
    
    def __init__(self, name, language):
        self.name = name
        self.language = language
        
    def info(self):
        print("my name is %s. I like %s." % (self.name, self.language))
        
# 实例化对象
message = Message("fengdi", "python")

print(Message)
print(message)

message.info()  # 调用实例方法

# 执行结果
<class '__main__.Message'>
<__main__.Message object at 0x10b14e320>
my name is fengdi. I like python.
1.2 类属性和实例属性
  • 类属性在类内部定义,可使用类名和实例名访问(类和实例共享)。当通过实例访问属性时,先从实例属性内查找,找不到则会到类属性中查找,类属性找不到报错。
  • 实例属性实例独有。实例属性可在初始化方法内定义,也可使用实例对象动态添加。
# 类属性和实例属性
class Test(object):
    
    message = "hello world"  # 类属性
    
    def __init__(self,name, age):
        # 实例属性
        self.name = name
        self.age = age
        
test = Test("fengdi", 15)

print(Test.message)  # 通过类名访问类属性
print(test.message)  # 通过实例对象访问类属性(前提是实例对象没有这个同名属性)

test.message = "python" # 动态添加属性,此时相当于给实例添加了一个同名的实例属性
print(test.message) # 此时同名实例属性会屏蔽类属性

# 执行结果
hello world
hello world
python
1.3 私有属性及方法
  • 以__开头的属性和方法为私有变量或私有方法,只能从内部访问,外部不能访问(伪私有:改名而已)
  • 以_开头和_结尾的变量为特殊变量,可直接访问
  • 以单下划线_开头的变量说明虽然可以被访问,但请将其视为私有变量,不可随便访问
# 私有属性和方法
class Message(object):
    
    def __init__(self, name, language, age, score):
        self.name = name
        self._language = language  # 外部可访问,但是默认将其视为私有属性,不能随便访问
        self.__age = age  # 私有属性:只能在内部访问,外部访问会报错
        self.__score = score
        
    def get_age(self):  # 私有属性可通过定义方法访问
        return self.__age
    
    def __getscore(self):  # 私有方法:只能在内部访问,外部访问会报错
        return self.__score
    
    def get_score(self):
        return self.__getscore()
    
# 实例化对象    
message = Message("fengdi", "python", 20, 85)
print(dir(message))  # 打印实例对象所有方法

# 访问属性及方法
print(message.name)  # 公有属性
print(message._language)  # 默认将其视为私有属性,不能随便访问
print(message.get_age())  # 通过公有方法访问私有属性
print(message.get_score())  # 通过公有方法访问私有方法

# 执行结果
['_Message__age', '_Message__getscore', '_Message__score', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_language', 'get_age', 'get_score', 'name']
fengdi
python
20
85
1.4 获取对象信息
  • 可使用type()函数获取对象信息
  • 使用isinstnace(),判断对象是否为指定的类型
  • hasattr(obj, name)函数查看对象是否有某个属性
  • getattr(obj, name)函数查看对象属性的值
  • setattr(obj, name, value)函数设定对象属性的值,相当于obj,attr = value
  • dir()函数查看对象所有属性和方法

2. 继承和多态

面向对象的程序设计有三个特点:封装、继承和多态。

  • 封装 根据职责将属性和方法封装到一个抽象的类中
  • 继承 实现代码的重用,相同的代码不需要重复的编写
  • 多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
2.1 继承

继承拥有以下特点:

  • 子类具有父类的所有属性和方法

    • 属性分为类属性和实例属性
    • 实例属性可通过实例对象或初始化方法_init_定义,类属性可在类中直接定义
    • 类属性,所有实例共享;实例属性实例独有
    • 实例属性优先级较高,同名的实例属性会屏蔽类属性
  • 可重新定义子类的某些属性,重写某些方法,即覆盖父类中的属性和方法(子类和父类中有相同的属性和方法时,父类会被覆盖)

  • 可为子类追加新的属性和方法

单继承:继承自一个类

# 继承
class Animal(object):
    """define a Animal class"""
    def __init__(self, name):
        self.name = name

    def get_name(self):
        print("Hello, I am %s." % self.name)
    
    def print_info(self):
        print("hello world!!")

class Dog(Animal):
    """define a Dog class, and it inherit from Animal class"""
    pass


class Cat(Animal):
    """define a Cat class, and it inherit from Animal class"""
    def get_name(self):  # 重写父类中的get_name方法
        print("cat's name is %s." % self.name)

    def run(self):  # 子类定义新的方法
        print("I'm running.I'm running.")
    
    def print_info(self):
        super().print_info()
        print("扩展父类print_info函数功能")

# 查看父类
print(Animal.__bases__)
print(Dog.__bases__)
print(Cat.__bases__)

# 实例化Animal类
animal = Animal("西瓜")
print(animal.name)
animal.get_name()
animal.print_info()

# 实例化Dog类,其自动拥有父类Animal类的属性和方法
dog = Dog("旺财")
print(dog.name)  # 继承父类name属性
dog.get_name()  #  继承父类get_name方法
dog.print_info() #  继承父类print_info方法

# 实例化Cat类,自定拥有父类属性和方法,也可重写父类方法、扩展父类方法、追加新的方法。
cat = Cat("薯条")
print(cat.name)  # 继承父类name属性
cat.get_name()  #  重写父类get_name方法
cat.run()  # 子类追加新的方法
cat.print_info()  # 使用super()函数扩展父类方法功能

# 执行结果

(<class 'object'>,)
(<class '__main__.Animal'>,)
(<class '__main__.Animal'>,)
西瓜
Hello, I am 西瓜.
hello world!!
旺财
Hello, I am 旺财.
hello world!!
薯条
cat's name is 薯条.
I'm running.I'm running.
hello world!!
扩展父类print_info函数功能

多继承:继承于多个类

  • 在搜索方法时,是按照 _mro_ 的输出结果 从左至右的顺序查找的
  • 如果在当前类中找到方法,就直接执行,不再搜索
  • 如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索
  • 如果找到最后一个类,还没有找到方法,程序报错
# 多继承
class A(object):
    
    def info(self):
        print("hello A class")
        
class B(object):
    
    def info(self):
        print("hello B class")

# 类C继承于A和B类
class C(A, B):
    
    pass

c = C()
print(C.__mro__)  # __mro__:查看类的属性、方法调用顺序
c.info()

# 执行结果

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
hello A class
2.2 super()
  • 实现在子类中调用父类的某个方法。多用于在子类中扩展父类的某个方法。
  • super函数会寻找当前类在类继承链中的下一个类进行继承(mro顺序:类继承链)
# super函数
class Animal(object):
    def __init__(self, name):
        self.name = name

    def greet(self):
        print('Hello, I am %s.' % self.name)

class Cat(Animal):
    def greet(self):
        super().greet()  # 调用当前类在类继承链中的下一个类中的greet方法
        print('wangwang.....')

cat = Cat('yuxi')
cat.greet()

# 执行结果

Hello, I am yuxi.
wangwang.....
2.3 多态
  • 多态指对不同类型的对象进行相同的操作,表现出不同的行为。
  • 多态通过继承和方法重写实现。
# 多态:不同对象调用相同方法的不同表现。通过继承和方法重写实现。
class Animal(object):
    """define a Animal class"""
    def __init__(self, name):
        self.name = name

    def greet(self):
        return "Hello, I am %s." % self.name

class Dog(Animal):
    """define a Dog class, and it inherit from class Animal"""
    def greet(self):
        return "wangwang....., I am %s." % self.name

class Cat(Animal):
    """define a Cat class, and it inherit from class Animal"""
    def greet(self):
        return "miaomiao....., I am %s." % self.name

def hello(animal):  # 对不同的对象进行相同的操作,做出不同的响应
    return animal.greet()

dog = Dog("dog")
dog_info = hello(dog)
print(dog_info)

cat = Cat("cat")
cat_info = hello(cat)
print(cat_info)

# 执行结果

wangwang....., I am dog.
miaomiao....., I am cat.

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 8,787评论 1 27
  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 882评论 0 6
  • 如何穿出并活出女子力? 1 3月的天气不冷也不热,鼓励着时装精们释放自我,因为此时无论穿着何种厚度的衣服在此时都无...
    LDP爱舞祷karry阅读 71评论 0 0
  • ByMary T. Caserta, MD, Professor of Pediatrics, Division ...
    Barreto阅读 778评论 0 0