Python day7 面向对象编程 (1)

2024-07-31 16:59:57 浏览数 (1)

面向对象编程 OOP

Object Oriented Programming,一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数

面向过程和面向对象

  • 面向过程,把函数继续切分为子函数
  • 面向对象,把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递

对象

自定义的对象数据类型就是面向对象中的类(Class)的概念

首先必须创建出这个学生对应的对象,然后,给对象发一个print_score消息,让对象自己把自己的数据打印出来

代码语言:python代码运行次数:0复制
class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

    def print_score(self):
        print('%s: %s' % (self.name, self.score))

类(Class)和实例(Instance)

面向对象最重要的概念就是类(Class)和实例(Instance)

Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student

代码语言:python代码运行次数:0复制
#class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object)
class Student(object):  
    pass

#创建建实例是通过类名 ()实现的:
bart = Student()
# bart绑定一个name属性
bart.name = 'Bart Simpson'


#在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去
class Student(object):
    def __init__(self, name, score): #self,表示创建的实例本身
        self.name = name
        self.score = score

访问限制

由于外部代码还是可以自由地修改一个实例的属性,我们可以把属性的名称前加上两个下划线__,变成了一个私有变量(private),只有内部可以访问,外部不能访问

代码语言:python代码运行次数:0复制
class Student(object):
    def __init__(self, name, score): #self,表示创建的实例本身
        self.__name = name
        self.__score = score
        
        #利用方法使得外部代码可以访问
        def get_name(self): 
        return self.__name
        #利用外部代码修改score
        def set_score(self, score):
        self.__score = score

继承和多态

我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)

代码语言:python代码运行次数:0复制
class Animal(object):   #编写Animal类
    def run(self):
        print("Animal is running...")

class Dog(Animal):  #Dog类继承Amimal类,没有run方法
    pass

class Cat(Animal):  #Cat类继承Animal类,有自己的run方法
    def run(self):
        print('Cat is running...')
    pass

class Car(object):  #Car类不继承,有自己的run方法
    def run(self):
        print('Car is running...')

class Stone(object):  #Stone类不继承,也没有run方法
    pass

def run_twice(animal):
    animal.run()
    animal.run()

run_twice(Animal())
run_twice(Dog())
run_twice(Cat())
run_twice(Car())
run_twice(Stone())

输出结果

Animal is running... Animal is running...

Animal is running... Animal is running...

Cat is running... Cat is running...

Car is running... Car is running...

AttributeError: 'Stone' object has no attribute 'run'

由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思

这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

获取对象信息

type()函数

它返回对应的Class类型。如果我们要在if语句中判断,就需要比较两个变量的type类型是否相同

  • 基本数据类型就是int,str
  • 对象是函数的话,用types模块中定义的常量:types.FunctionType,types.BuiltinFunctionType,types.LambdaType,types.GeneratorType

isinstance()函数(优先)

对于class的继承关系来说,使用type()就很不方便。我们要判断class的类型,可以使用isinstance()函数

  • isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上
  • 还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是list或者tuple
代码语言:python代码运行次数:0复制
>>> isinstance([1, 2, 3], (list, tuple))
True
>>> isinstance((1, 2, 3), (list, tuple))
True

dir()函数

它返回一个包含字符串的list

仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态

代码语言:python代码运行次数:0复制
>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()
>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404

>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x10077a6a0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

实例属性和类属性

为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加

代码语言:python代码运行次数:0复制
class Student(object):

count = 0

def __init__(self, name):

self.name = name

Student.count  = 1

发现没有直接点明init这个方法,在实例化对象的时候,应该是会自动调用一次这个方法

0 人点赞