Python -- 面向对象高级编程

作者: 2023开始学 | 来源:发表于2019-03-03 19:32 被阅读13次

面向对象设计中最基础的3个概念:数据封装、继承和多态

使用_ slots _

_ slots _的作用:限制实例的属性

为了达到限制的目的,在定义class时,定义一个_ slots _特殊变量,来限制该class实例添加的属性:

注意:
1、_ slots _仅对当前类实例起作用,对继承的子类是不起作用的

2、如果子类中也定义_ slots ,那么子类实例允许添加的属性就是自身的 slots 加上父类的 slots _

3、使用_ slots _添加属性时,一定要给属性加上引号

方法:为了给各个实例都绑定方法,可以给class绑定方法

通常情况下,添加方法可直接定义在类中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。

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

s=Student() #创建一个实例
s.name='Maria'
s.age=23
# s.score=99  由于在类Student中限制了属性,所以添加score就会报错
print("s.name:",s.name)
print("s.age:",s.age)

print("给s实例添加score属性后,报错类型为:")
try:
    s.score=99
except AttributeError as e:
    print("AttributeError:",e)

print('    ')
print("下面定义了子类:")
class Graduate(Student):  #继承了Student类,那么也继承了Student类的_ _slots_ _
    __slots__=('score')  #这在子类中也定义了_ _slots_ _
#看出下面g.name和g.age都正常,说明子类继承了Student类的_ _slots_ _
g=Graduate()
g.score=99
g.name='shirley'
g.age=34
print("g.name,g.age:",g.name,g.age)
print("g.score:",g.score)
image.png

@property

class Student(object):
    @property
    def score(self):
        return self._score  #是self._score,不是self.score,中间的下划线不能省略

    @score.setter
    def score(self,value):   #都是raise ValueError, V和E要大写,先判断输入的数是不是Int,再判断是否在100以内
        if not isinstance(value,int):
            raise ValueError("please input an integer")
        elif value<0 or value>100:
            raise ValueError("请输入0到100之间的数!!!")
        else:
            self._score=value

s=Student()
s.score=99
print("s.score:",s.score)
print("    ")
s1=Student()
s1.score=999
print("s1.score的分数:",s1.score)
image.png
class Screen(object):
    __width = 0

    def get_width(self):
        return self.__width

    @property
    def width2(self):
        return self.__width

s = Screen()
print("type(s.get_width)类型为:",type(s.get_width)) # <class 'method'>
print("type(s.width2)类型为:",type(s.width2)) # <class 'int'>
image.png

实战:请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution:

class Screen(object):
    @property
    def width(self):
        return self._width
    @width.setter
    def width(self,value):
         self._width =value

    @property
    def height(self):
        return self._height
    @height.setter
    def height(self,value):
         self._height=value

    @property
    def resolution(self):  #此处将resolution定义为只读属性
        return self.width*self.height

s = Screen()
s.width = 1024
s.height = 768
print('resolution =', s.resolution)
if s.resolution == 786432:
    print('测试通过!')
else:
    print('测试失败!')

运行结果:


image.png

多重继承

参考:https://kevinguo.me/2018/01/19/python-topological-sorting/

多重:多个, 多重继承:即同时继承多个对象

 通过多重继承,一个子类就可以同时获得多个父类的所有功能

MixIn

在设计类的继承关系时,通常,主线都是单一继承下来的,但是,如果需要“混入”额外的功能,通过多重继承就可以实现,这种设计通常称之为MixIn.

python允许使用多重继承,因此,MixIn就是一种常见的设计

只允许单一继承的语言(如JAVA),不能使用MixIn设计

目的:MixIn主要解决对同一对象用不同标准来分类的问题。从性别划分,你是男人;从国家划分,你是中国人;从职业划分,你是程序员; mixin可以轻松定义具备跟你一样特征的人:中国男程序员(天朝屌丝逗比程序员)

定制类

_ str _

将__str__方法理解成,规范化输出格式,输出用户能看懂的格式

_ repr _

1、直接显示变量调用的不是str( ),而是repr( ),两者的区别:

      __str__( )返回用户看到的字符串

     __repr__( )返回程序开发者看到的字符串,__repr__( )是为调试服务的

2、通常情况下,repr( )和 str( )的代码相同,所以偷懒时可以写成这种形式:repr=str ,类似赋值,把str 里的代码赋给repr

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

s = Student("Michael")
print(s)

运行结果:

image.png

下面使用了str方法后:

class Student(object):
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return 'Student Object (name :%s) ' % self.name  #返回的内容,自己可以修改

s=Student("Michael")
print(s)

运行结果:


image.png

str方法 return 后面的语句可以自己修改

class Student(object):
    def __init__(self,name):
        self.name=name
    def __str__(self):
        return "Hello, My name is %s" % self.name

s=Student("Michael")
print(s)

运行结果:


image.png

_ iter _

如果一个类想被用于for ……in 循环,类似list、tuple那样,就必须使用一个iter( )方法, 该方法返回一个迭代对象

举例:以斐波那契数列为例,写一个Fib类,可以作用于for循环:

#下面是__iter__方法
class fib(object):
    def __init__(self):
        self.a,self.b=0,1

    def __iter__(self):  #__iter__方法,返回一个迭代对象
        return self

    def __next__(self):
        self.a,self.b=self.b,self.a+self.b
        if self.a>100:
            raise StopIteration
        return self.a

for n in fib():
    print(n)
image.png

_ getitem _

  取下标

__getitem__( self, item)方法

item看作是“下标”, getitem( )传入的参数可能是一个int,也可能是一个切片对象slice

 与 __getitem__对应的是__setitem__( )方法,__delitem__( )方法
class fib(object):
    def __init__(self):
        self.a,self.b=0,1

    def __iter__(self):  #__iter__方法,返回一个迭代对象
        return self

    def __next__(self):
        self.a,self.b=self.b,self.a+self.b
        if self.a>100:
            raise StopIteration
        return self.a

    def __getitem__(self,n):  #__getitem__方法
        a,b=1,1
        for x in range(n):
            a,b = b, a+b
        return a

f=fib()
print('f[0]:',f[0])
print("f[1]:",f[1])
print("f[2]:",f[2])
print("f[3]:",f[3])
print("f[13]:",f[13])

运行结果:


image.png

_ getattr _

 正常情况下,当调用的类的方法或属性不存在时,就会报错。
class Student(object):
    def __init__(self):
        self.name="lily"

s=Student()
print("s.name:",s.name)
print("    ")
print("s.score:",s.score)
print("s.score函数:",s.score())
由于类中没有score属性时,调用会报错

print("s.score:",s.score)语句的报错结果:

image

print("s.score函数:",s.score)语句的报错结果:

image

添加getattr方法后: return 99,所以调用时s.score即可

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

    def __getattr__(self, attr): #__getattr__方法
        if attr == 'score':
            return 99
           


s=Student()
print("s.name:",s.name)
print("    ")
print("s.score:",s.score)

返回函数也是可以的: return lambda : 25,所以调用时是s.score()

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

    def __getattr__(self, attr): #__getattr__方法
        if attr == 'score':
            return lambda :25  #此处是匿名函数lambda, 之前只是返回一个数值, return 99
            # print('hell')


s=Student()
print("s.name:",s.name)
print("    ")
print("s.score:",s.score())#由于return后面返回的是一个函数,因此这里调用时应该是s.score(),带上括号,
# 而如果是return 99, 则调用时不必带括号

运行结果和上面相同:

image

_ call _

调用实例方法时,使用“instance.method( )”形式来调用

问题:能不能直接在实例本身上调用呢?在python中,是肯定的

结果:任何类,只需要定义一个__call( )方法,就可以直接对实例进行调用
class Student(object):
    def __init__(self,name):
        self.name=name

    def __call__(self):
        return 'my name is %s' %self.name

s=Student('lily')
print(s())
image.png

相关文章

  • 动手理解Python的引用、赋值、拷贝

    Python是一门面向对象的高级编程语言,相较于其他面向对象的编程语言,Python在面向对象的路上走得更远,即,...

  • Python从入门到精通

    Python语法的三个阶段 Python基础语法函数是编程 Python进阶语法面向对象编程 Python高级语法...

  • 廖雪峰python3 教程

    观其大纲 1 python基础 2 函数 3 高级特性 4 函数式编程 5 模块 6 面向对象编程 7 面向对象高...

  • 面对对象高级编程

    面向对象高级编程: 面向对象编程:封装、继承和多态 面向对象高级编程:多重继承、定制类和元类

  • Python 面向对象编程

    Python 面向对象编程(一) Python 面向对象编程(一) 虽然Python是解释性语言,但是它是面向对象...

  • 无标题文章

    Python 非常易学,强大的编程语言。Python 包括高效高级的数据结构,提供简单且高效的面向对象编程。 所谓...

  • python面向对象学习笔记-01

    学习笔记 # 0,OOP-Python面向对象 - Python的面向对象 - 面向对象编程 - 基础 -...

  • 推荐10 款最好的 Python IDE

    Python 非常易学,强大的编程语言。Python 包括高效高级的数据结构,提供简单且高效的面向对象编程。Pyt...

  • 10款最受Python开发者欢迎的Python IDE

    Python 非常易学,强大的编程语言。Python 包括高效高级的数据结构,提供简单且高效的面向对象编程。 Py...

  • 学习python最好的10款编辑器,你用过哪几个?

    Python 非常易学,强大的编程语言。Python 包括高效高级的数据结构,提供简单且高效的面向对象编程。 Py...

网友评论

    本文标题:Python -- 面向对象高级编程

    本文链接:https://www.haomeiwen.com/subject/nqumuqtx.html