python3 面向对象_Python3 面向对象

1.面向对象

把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

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

classStudent(object):def __init__(self, name, score):

self.name=name

self.score=scoredefprint_score(self):print('%s: %s' % (self.name, self.score))

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

类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

方法:类中定义的函数。

类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

局部变量:定义在方法中的变量,只作用于当前实例的类。

实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。

继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

实例化:创建一个类的实例,类的具体对象。

对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

2.类和实例

必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

classStudent(object):def __init__(self, name, score): #构造方法

self.name =name

self.score=scoredefget_grade(self):if self.score >= 90:return 'A'

elif self.score >= 60:return 'B'

else:return 'C'bart= Student('Bart Simpson', 59)print(bart.get_grade())

class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的,如果没有合适的继承类,就使用object类,这是所有类最终都会继承的类。

注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

创建实例的时候,必须传入与__init__方法匹配的参数。

要定义一个方法,除了第一个参数是self外,其他和普通函数一样。要调用一个方法,只需要在实例变量上直接调用,除了self不用传递,其他参数正常传入:

classStudent(object):def __init__(self, name, score): #构造方法

self.__name =name

self.__score =score

defget_name(self):return self.__name

defget_score(self):return self.__score

defset_score(self, score):if 0 <= score <= 100:

self.__score =scoreelse:raise ValueError('bad score')

bart= Student('Bart Simpson', 59)

bart.set_score(100)print(bart.get_score(),bart.get_name())

bart._Student__name ###这样可以从外部访问了,但是不建议。

内部属性不被外部访问,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

这样代码更健壮,可以对参数做检查,避免传入无效的参数

在Python中,变量名类似__xxx__的,就是以双下划线开头,并且以双下划线结尾,是特殊变量,特殊变量可以直接访问,不是private变量,不能用__name__、__score__这样的变量名。

以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,把它当成私有变量。

__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。

类的专有方法:可以对类的专有方法进行重载(用到具体的搜索吧)

__init__ : 构造函数,在生成对象时调用

__del__ : 析构函数,释放对象时使用

__repr__ : 打印,转换

__setitem__ : 按照索引赋值

__getitem__: 按照索引获取值

__len__: 获得长度

__cmp__: 比较运算

__call__: 函数调用

__add__: 加运算

__sub__: 减运算

__mul__: 乘运算

__truediv__: 除运算

__mod__: 求余运算

__pow__: 乘方

3.继承和多态

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

子类获得了父类的全部功能,但当子类和父类有相同的方法时,子类覆盖了父类的该方法,先调用子类的相同方法。

super() 函数是用于调用父类(超类)的一个方法super(dog, self).__init()__(name)

基类可以定义在别的模块中,classDerivedClassName(modname.BaseClassName): 但是要导入该模块import。

Python同样有限的支持多继承形式。需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索,方法在子类中未找到时,从左到右查找父类中是否包含方法。

classDerivedClassName(Base1, Base2, Base3):.

.

.

继承示例代码:

classAnimal(object):def __init__(self):

a= "animal"

defrun(self):print('Animal is running...')classDog(Animal):defrun(self):print('Dog is running...')defeat(self):print('Eating meat...')

dog=Dog()print(isinstance(dog, Dog))

Python中多态是指一类事物有多种形态。比如动物有多种形态,人,狗,猫,等等。文件有多种形态:文本文件,可执行文件。

多态性:

为什么要用多态性?

①增加了程序的灵活性

以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)

②增加了程序额可扩展性

通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用

importabcclass Animals(metaclass=abc.ABCMeta):

@abc.abstractmethoddeftalk(self):pass

classPeople(Animals):deftalk(self):print('People is talking')classCat(Animals):deftalk(self):print('Cat is miaomiao')classDog(Animals):deftalk(self):print('Dog is wangwang')

cat1=Cat()

dog1=Dog()

peo1=People()#peo、dog、pig都是动物,只要是动物肯定有talk方法#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用

peo1.talk()

dog1.talk()

peo1.talk()#定义一个统一的接口来访问

deffunc(obj):

obj.talk()

func(cat1)

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

4.获取对象信息

判断对象类型,使用type()函数。如果要判断一个对象是否是函数等,可以使用types模块中定义的常量。

isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。

获得一个对象的所有属性和方法,可以使用dir()函数。

通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。

配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态。参考菜鸟python3 内置函数。

5. 实例属性和类属性

直接在class中定义属性,这种属性是类属性,归类所有。类的所有实例都可以访问到。相同名称的实例属性将屏蔽掉类属性。

访问类的变量是通过“类名.变量名”进行访问,而不是“self.变量名”进行访问。“self.变量名”访问的是实例对象的自身变量。

下面例子中实例的变量被重新绑定,

classff:

a = 5

defaaa(self):

print(ff.a) #如果写成self.a,a1.a变量被重新绑定,a1.aaa()的值就是10. 就取不到类的变量。

a1 =ff()

a1.aaa()

a2 =ff()

a2.aaa()

a1.a = 10

print(a1.a)

print(a2.a)

ff.a = 100

print(a1.a)

print(a2.a)

a1.aaa()

a2.aaa()

result:

5

5

10

5

10

100

100

100

6.使用__slots__

可以给一个实例绑定方法和属性,但对别的实例是不起作用的。

只允许对Student实例添加name和age属性。

classStudent(object):__slots__ = ('name', 'age') #用tuple定义允许绑定的属性名称s=Student()

s.name= "sss"s.score= 99

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。

在子类中也定义__slots__,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。

7.使用@property

读,写,删除的例子。三种操作对应了一个名字。

class People(object):

def __init__(self, name, age):

self.name = name

self.age = age

# 私有属性

self.__number = 0

# 获取私有属性值 number = p1.number 会执行这个函数

@property

def number(self):

# 返回私有属性值

return self.__number

# 设置私有属性值 p1.number = 666

@number.setter

def number(self, value):

# 设置__number的值

self.__number = value

# 删除私有属性 del p1.number 会执行这个函数

@number.deleter

def number(self):

# 删除属性

del self.__number

p1 = People('张三', 22)

# 正常的对象属性赋值

# 对象.属性名 = 属性值

p1.name = '李四'

# 获取对象的属性值

name = p1.name

# 删除对象的属性

del p1.name

# 私有属性升级版

# 会去执行@property装饰number函数,函数执行完成后返回一个结果

num = p1.number

print(num)

# 会去执行@number.setter装饰的number函数,在函数中设置__number属性的值

p1.number = 666

# 会去执行@property装饰number函数,函数执行完成后返回一个结果

print(p1.number)

# 会去执行@number.deleter装饰的number函数,在函数中会将__number属性删除

del p1.number

# 会去执行@property装饰number函数,函数执行完成后返回一个结果

print(p1.number)

birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来。

classStudent(object):

@propertydefbirth(self):returnself._birth

@birth.setterdefbirth(self, value):

self._birth=value

@propertydefage(self):return 2015 -self._birth

s=Student()

s.birth= 5

print(s.birth)

8.多重继承

在设计类的继承关系时,通常,主线都是单一继承下来的,例如,Ostrich继承自Bird。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,比如,让Ostrich除了继承自Bird外,再同时继承Runnable。这种设计通常称之为MixIn。

classDog(Mammal, RunnableMixIn, CarnivorousMixIn):pass

9.检查对象的特性

hasattr() 函数用于判断对象是否包含对应的属性。语法:hasattr(object,name)

getattr() 函数用于返回一个对象属性值。语法:getattr(object,name[,default])default -- 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError。

c =ff()print(hasattr(c, 'age')) #检查实例属性是否拥有

print(hasattr(c, 'study')) #检查实例方法是否拥有

print(callable(getattr(c, 'study',None))) #检查实例方法study能否被调用

是否拥有

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值