日知录(五):python面对对象编程

2022-08-07

OOP

理解OOP的想法

终于到这个part了,如何面对对象编程呢?
来一个高大上的定义:面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
之前学的是C语言,是一种面向过程的程序设计思想。
1.在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。
2.类(Class)和实例(Instance)的概念
Class是一种抽象概念,比如我们定义的Class——Student,是指学生这个概念,而实例(Instance)则是一个个具体的Student,比如,Bart Simpson和Lisa Simpson是两个具体的Student。
3.面向对象的设计思想是抽象出Class,根据Class创建Instance。
4.我大白话讲讲:简单点理解,动物分类:界门纲目科属种,比如狼这一实例属于犬科,犬科的基本特点,在_init_内定义(数据封装)。狼在继承犬科(继承)这一基本特点后,还有一些自己的特点,或者可以重新定义一些基本特点(多态性)。同时,犬科与猫科之间,必定是由一些特点是根本性的,不能改变的。(即 该类的私有属性)

接下来看看我们对象的特性

特点一:数据封装

# -*- coding: UTF-8 -*-
 #创建一个新的抽象类:用class语句,Student为类的名称
class Student(object):                     
#__init__()是一种特殊的方法,被称为类的构造函数或初始化方法
    def __init__(self,name,score):          
        self.name=name   					
        self.score=score
#slef代表类的实例,self在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。

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

#创建类的实例对象bart,并通过__init__方法接收参数
bart = Student('Bart Simpson', 5)
#访问对象的属性.print_score()
bart.print_score()

该例中定义了print_score()方法,即在Student类的内部定义访问数据的函数print_score(),这样,就把“数据”给封装起来了。这些封装数据的函数是和Student类本身是关联起来的,我们称之为类的方法。

定义方法时进行数据封装

1.定义一些特殊方法

一般是系统定义名字,类似__init()__之类的

  1. __foo __(): 定义的是特殊方法,一般是系统定义名字 ,类似 __ init __() 之类的。
  2. _foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *

2.定义类的私有属性

__private_attrs: 两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs

3.定义类的方法

def 关键字:在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数

4.定义类的私有方法

__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods
试图从外部访问私有变量时的报错

# -*- coding: UTF-8 -*-

class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0  # 公开变量

    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print(self.__secretCount)


counter = JustCounter()
counter.count()
counter.count()
print(counter.publicCount)
print(counter.__secretCount ) 
# 报错,实例不能访问私有变量
AttributeError: 'JustCounter' object has no attribute '__secretCount'

Python不允许实例化的类访问私有数据,但你可以使用 object._className__attrName( 对象名._类名__私有属性名 )访问属性

# -*- coding: UTF-8 -*-

class Runoob:
    __site = "www.runoob.com"

runoob = Runoob()
print (runoob._Runoob__site)

结果

www.runoob.com

特点二:继承

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

1.继承1个类

class 派生类名(基类名)
···

2.继承多个类

class A:        # 定义类 A
.....

class B:         # 定义类 B
.....

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

3.方法重写

如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法

class Animal(object):
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    def run(self):
        print('Dog is running...')

    def eat(self):
        print('Eating meat...')

class Cat(Animal):
    def run(self):
        print('Cat is running...')

dog = Dog()
dog.run()

cat = Cat()
cat.run()

运行结果

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

当子类和父类都存在相同的run()方法时,调用时子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。这样,我们就获得了继承的另一个好处:多态

特点三:多态性

多态的好处就是,当我们需要传入Dog、Cat、Tortoise……时,我们只需要接收Animal类型就可以了,因为Dog、Cat、Tortoise……都是Animal类型,然后,按照Animal类型进行操作即可,牵一发而动全身的感觉,就是从父类更改就可以。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态。

获取对象信息

在引用对象时,了解对象的类型和方法

1. type()

2. isinstance()

要判断class的类型,可以使用isinstance()函数

3. dir()

要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list。
配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态

类属性与实例属性

实例绑定属性的方法是通过实例变量,或者通过self变量

class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90

以下摘自廖雪峰老师的教程实例。
当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。来测试一下:

>>>class Student(object):
	name = 'Student'

>>>s = Student() # 创建实例s
>>>rint(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student

>>>print(Student.name) # 打印类的name属性
Student

>>>s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael

>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student

>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

在编写程序的时候,不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。

本文地址:https://blog.csdn.net/weixin_43883903/article/details/107175514