面向对象,类的引入

面向对象

编程方式
  • 面向过程
  • 函数式编程
  • 面向对象
面向过程
  • 之前所用的,按照解决问题的步骤,一步步的按流程进行,有先后之分。整个设计流水线式的,思维比较机械化。

  • 优缺点:

    • 优点 : 复杂的问题流程化,将问题分解简化。
    • 缺点:拓展性不足
面向对象
定义

核心是对象.对象是一个数据以及其相关行为的集合,

面对对象是功能上指向建模对象,通过数据和行为方式来描述交互对象的集合.

在python中,一切皆为对象.

优缺点
  • 优点

可以解决程序的拓展性

  • 缺点

就是复杂度远高于面向过程.

交互式解决问题无法准确预测结果

内容
  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • **方法:**类中定义的函数。
  • **类变量:**类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • **数据成员:**类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • **方法重写:**如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • **局部变量:**定义在方法中的变量,只作用于当前实例的类。
  • **实例变量:**在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
  • **继承:**即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • **实例化:**创建一个类的实例,类的具体对象。
  • **对象:**通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

举例

object1:Tom
   特征:
     scool=zucc
     name=tom
     age=21
     sex=male
     技能:ballgame  study ...
object2:Bob
     scool=zucc
     name=bob
     age=22
     sex=male
     技能:tennis  study ...

类就是类别,种类.

对象就是特征和技能的统一体.

类就是这一系列相似对象的特征和技能的结合.

对应现实生活,先有个体(对象),才有类别;但是对于程序,必须先有类,然后才有对象.

面向对象编程引入
定义

OOP(object oriented programming)即面向对象编程

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

在python中,所有数据类型都可以视为对象,当然也可以自定义对象.

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

举例

如要处理我们的成绩.为了表示学生的成绩:

  • 面向过程的方式
st1={'name':'jack','score':80}
st2={'name':'bob','score':97}...
def show_score(st):
	print(st['name'],st['score'])
show(st1)
  • 面向对象
class student:
    def __init__(self,name,score):
        self.name=name
        self.score=score
    def show_score(self):
        print(self.name,':',self.score)
st1=student('bob',97)
st1.show_score()
类的定义

面向对象设计的思想,先抽象出类,再根据类创建实例.

命名类名时 变量名称各个单词首字母大写

创建一个空类

class MyFirstClass:
	pass

创建一个普通类

class ClassName(object):
	'''dicstring(说明文档)'''
	class_statement
class Student:
    school='ZUCC'#所有对象的固有属性
    def __init__(self,name,score):
        self.name=name
        self.score=score
    def show_score(self):
        print(self.name,':',self.score)
st1=Student('bob',97)#实例化
print((st1.name,st1.score,st1.school))
('bob', 97, 'ZUCC')
总结

类的作用是一个模板.我们可以在创建实例的时候,把一些我们认为必须要绑定的属性填写进去.这时就通过特殊的__init__方法.在创建实例的时候,绑定相关的属性.

和普通函数相比,在类中定义方法时,第一个参数必须是self.除第一个参数外,其他的与普通函数没有什么区别.

self代表的是实例,而非类

__init__方法

  • 为对象初始化自己独有的特征
  • 该方法中可以有任意的代码,但是不能有返回值
数据封装
class Student:
    school='ZUCC'#所有对象的固有属性
    def __init__(self,name,score):
        self.name=name
        self.score=score
st1=Student('bob',97)#实例化

我们通过__init__st1实例本身有了相关的数据,我们可以直接在Student类的内部定义相关的函数来访问数据,以此封装数据.

这些封装数据的函数和Student类本身是关联起来的,他们被称之为方法.

类的两个作用
  • 类名引用

    • 类名.属性
  • 实例化

​ 类名加上一个括号就是实例化,它能够自动触发__init__函数,进而为每个实例定制自己的特征

  • 类属性的补充

类属性的查看

  • dir()来查看对应类包含的属性(返回列表)

  • 类名.__dict__返回一个字典,key为属性名,value为属性值

特殊的类属性

类名.__name__返回类的名字

类名.__doc__返回类的文档字符串

类名.__base__返回类的第一个父类

类名.__bases__返回类的所有父类(元组)

类名.__module__返回类定义所在的模块

类名.__class__返回实例对应的类

对象之间的交互

定义2个类,Person,Dog,都有体力及攻击值,可以进行攻击

class Person:
    def __init__(self,name,aggressivity,life_value):
        self.name=name
        self.aggre=aggressivity
        self.life_values=life_value
    def attack(self,dog):
        dog.life_values-=self.aggre

class Dog:
    def __init__(self,name,breed,aggressivity,life_vale):
        self.name=name
        self.breed=breed
        self.aggre=aggressivity
        self.life_values=life_vale
    def bite(self,people):
        people.life_values-=self.aggre

per=Person('bob',10,888)
dog=Dog('white','husky',12,480)
print('dog:',dog.life_values,',person:',per.life_values,sep='')
per.attack(dog)
dog.bite(per)
print('dog:',dog.life_values,',person:',per.life_values,sep='')

dog:480,person:888
dog:470,person:876
类命名空间与对象实例的空间

创建一个类就会创建一个类的名称空间,用来存储我们定义的所有的变量名。这些名字就是属性。

类的属性有两种

  • 静态 :直接在类中定义的变量

  • 动态 : 在类中定义的方法

静态属性是共享给所有对象的,动态属性是绑定到所有对象的

class Student:
    school='ZUCC'#所有对象的固有属性(静态)
    def __init__(self,name,score):
        self.name=name
        self.score=score
    def find_score(self): ##(动态)
        print(self.name,":",self.score)
st1=Student('bob',95)
st2=Student('jack',89)
print(id(st1.school),id(st2.school))
print(id(st1.find_score),id(st2.find_score),id(Student.find_score

4365888 4365888
4014768 4014768 12138368
类的三大特性
继承

在面向对象编程中,当我们定义一个新的类后,可以从某个现有的类,继承,新的类就被称为子类

SubClass,而被继承的类则被称为基类,父类,超累(Base Class,Father Class,Super Class)

#定义一个动物类(Animal),它有一个run()方法
class Animal:  #定义父类
    def run(self):
        print('Animal is running.')
class Dog(Animal): #括号内为所继承的类
    pass
class Cat(Animal): #单继承
    pass
class Husky(Animal,Dog): #多继承用逗号分隔开
    pass
Dog().run()    #继承Animal的run
Cat().run()
print(Dog.__bases__) #查看该类继承的父类
print(Animal.__bases__)

Animal is running.
Animal is running.
(<class '__main__.Animal'>,)
(<class 'object'>,)

如果不指定类,python类会默认继承object类

object是所有python类的基类,提供一些常见方法的实现

多态

当子类和父类存在相同名称的方法时,子类的方法会覆盖父类的方法,在运行代码时,总会调用子类的方法。

这样就是继承的另外一个好处,多态。

理解多态,首先要对数据类型再进行说明。定义一个类的时候实际上就是定义了一种数据类型。我们自定义的数据类型和python自带的数据类型(str,list,dict)等相同。

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

dog=Dog()
cat=Cat()
dog.run()
cat.run()

Dog is Running
Cat is Running
###isinstance判断所给的对象是不是所给的数据类型
li=[]
print(isinstance(li,list))
print(isinstance(dog,Animal))
print(isinstance(Dog,object))
True
True
True

对于一个变量,只要知道其父类型,无需确切知道其子类型,就可以调用相关的方法。运行时具体的方法是作用于子类型上还是作用于父类型上,由我们运行的对象决定。也就是说,在调用时只管调用,无需注意细节

当我们新增一个子类时,只要保证相关的方法编写正确,就不用再管原来的代码是怎么调用的

开闭原则
  • 对拓展开放:允许新增子类
  • 对修改封闭:不需要修改依赖父类类型的函数
总结

继承可以一级一级的继承下来

任何类都可以追溯到根类object

私有属性

在类的内部,可以有属性和方法,而外部代码就可以通过直接调用实例变量的方法来操作数据.这样,隐藏了内部的复杂逻辑

class Student:
    school='ZUCC'#所有对象的固有属性(静态)
    def __init__(self,name,score):
        self.name=name
        self.score=score
    def find_score(self): ##(动态)
        print(self.name,":",self.score)
st1=Student('bob',95)
st1.find_score()
st1.score=92
st1.find_score()

bob : 95
bob : 92

由上可知,外部代码可以自由修改一个实例的属性(name,score).

如果要让内部属性不被外部访问,我们可以在属性名称前面加__(2个下划线.)

在python中如果实例的变量名以双下划线开头,就变成了一个私有变量,只允许内部访问.

class Student:
    school='ZUCC'#所有对象的固有属性(静态)
    def __init__(self,name,score):
        self.name=name
        self.__score=score
    def find_score(self): ##(动态)
        print(self.name,":",self.__score)
st1=Student('bob',95)
st1.find_score()
print(st1.name)
print(st1.__score)
bob : 95 #成绩只能通过内部函数访问
bob    #可以直接外部访问
AttributeError: 'Student' object has no attribute '__score' #报错,无法直接无法及更改分数

如果想要更改私有变量,可以通过在类内定义更改该变量的函数,再在外部调用函数

class Student:
    school='ZUCC'#所有对象的固有属性(静态)
    def __init__(self,name,score):
        self.name=name
        self.__score=score
    def find_score(self): ##(动态)
        print(self.name,":",self.__score)
    def change_score(self,score):
        self.__score=score
st1=Student('bob',17)
st1.find_score()
st1.change_score(89)
st1.find_score()

bob : 17
bob : 89
########注:并非绝对无法从外部访问私有变量
print(st1._Student__score)
89
#可以以以上方式访问私有属性,但是不推荐这种方式.
封装
定义

隐藏对象的属性和实现细节,仅对外提供公共访问的方式

优点
  • 可以将变化隔离
  • 便于使用
  • 提高安全性
  • 提高复用性
原则
  • 将不需要对外提供的内容隐藏

  • 隐藏属性,提供公共方法对其进行访问

————>私有方法,私有变量------->私有属性

用双下划线开头标记私有属性

鸭子类型
解释

关于鸭子类型,在百科中是这么描述的:“鸭子类型”的语言是这么推断的:一只鸟走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,那它就可以被当做鸭子。也就是说,它不关注对象的类型,而是关注对象具有的行为(方法)。对于C++来说,我们要调用某个以类A为参数的函数,则我们传入的类型必须是类A类型,或者是类A的子类类型。但在Python中,却没有这个要求,它只要求我们在函数体中实现部分,在类B中同样也能实现,那么B就能传入函数中。

class obj1:
   def run(self):
       print('this is first')
class obj2:
   def run(self):
       print('this is second')
def runs(obj1):
   obj1.run()
StuA=obj1()
runs(StuA)
infA=obj2()
runs(infA)

this is first
this is second
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值