【Python】类和对象

 

目录

面向对象编程

封装(信息屏蔽)

继承(子类自动共享父类的方式)

多态

类相关知识

self

构造和析构

__init__(self, param1, param2...)

__new__(cls, ...)【极少使用】

私有变量

继承

Python支持多重继承

组合

类定义、类对象和实例对象

绑定

销毁类del

类相关内置方法

issubclass(classA, classB)

isinstance(obj, class)

hasattr(object, name)

getattr(obj, name [, default])

setattr(obj, name, value)

delattr(obj, name)

property(fget=None, fset=None, fdel=None, doc=None)

总结


对象=属性+方法

class Student:
    #属性
    color = 'green'
    weight = 10
    legs = 2
    shell = True
    mouth = '小嘴'

    #方法
    def climb(self):
        print('爬?')
    def run(self):
        print('跑a a a a a ')
    def walk(self):
        print('优雅~')

面向对象编程

封装(信息屏蔽)

继承(子类自动共享父类的方式)

多态

小甲鱼老师理解的多态比较深层,上栗A和B类均无父类,但可假设有一个父类,父类有一个fun方法,而A和B类都分别重载了fun方法,从而表现出同一个父类、同一个方法却表现不同的结果,而这就是多态。多态,其实可理解为,老虎、小鸟、猴子都是生物(继承于同一个父类名为“生物”),生物都有一种生存技能“逃跑”方法,但老虎、小鸟、猴子各自的逃跑方法是不一样的,这些【同父类、同方法签名、但方法实际效果不同】的情况就是多态。假设你作为宇宙观察者,看到了老虎、小鸟、猴子同时在逃跑,但它们的逃跑形式各自不一样,感叹地说道:“跑得真快,而且每一种都不一样~”

类相关知识

self

self相当于this指针(当前上下文对象),每一个方法第一个参数固定为self,调用方法时默认传递第一个参数self给方法自身,直接正常传第二个参数开始即可。

构造和析构

__init__(self, param1, param2...)

初始化方法

__init__方法必须返回的是None,返回其他会报错

__new__(cls, ...)【极少使用】

构造方法? __new__在__init__之前执行,需传入一个cls对象(由内存开辟空间后得到的一个对象)以及相关需要的参数,例如下面的str类就需要string参数传入

上栗子,属于继承不可变类型str,但又需要提前修改内容。具体是先继承了str类,再重写__new__,先将传入的string转大写,再继续执行str类的__new__方法并返回它的返回值。

私有变量

__name是私有变量,变量名前缀是双下划线'__'的,均为私有变量,否则公共变量(ps:可通过公共方法操作私有方法)

可以利用_类名__变量名访问,例如:

继承

import random as r

class Fish:
    def __init__(self):
        self.x = r.randint(0,10)
        self.y = r.randint(0,10)

    def move(self):
        self.x -= 1
        print("我的位置是:", self.x, self.y)

class GoldFish(Fish):
    pass

class Carp(Fish):
    pass

class Salmon(Fish):
    pass

class Shark(Fish):
    def __init__(self):
        self.hungry = True

    def eat(self):
        if self.hungry:
            print("饿饿!!!!!!饿!!!!!!")
            self.hungry = False
        else:
            print("太撑了 吃不下咯!")

shark的构造方法覆盖了父类的构造方法,导致x变量没有被初始化从而在move方法时进行算术运算报错,可改为如下两种方法解决。

推荐方法

因为能够一步到位地修改父类,而不需要改调用父类方法代码。例如修改Fish为FishA,下方不推荐方法处的Fish.__init__(self)要改为FishA.__init__(self)

class Shark(Fish):
    def __init__(self):
        super().__init__()
        self.isHungry = True

    def eat(self):
        if self.isHungry:
            print("饿饿!!!!!!饿!!!!!!")
            self.isHungry = False
        else:
            print("太撑了 吃不下咯!")

不推荐的方法

class Shark(Fish):
    def __init__(self):
        Fish.__init__(self) #新增一句代码,调用父类构造方法初始化x
        self.hungry = True

    def eat(self):
        if self.hungry:
            print("饿饿!!!!!!饿!!!!!!")
            self.hungry = False
        else:
            print("太撑了 吃不下咯!")

Python支持多重继承

不推荐使用多重继承,因为可能导致不可预知的bug

组合

class Turtle:
    def __init__(self,x):
        self.num = x

class Fish:
    def __init__(self,x):
        self.num = x

class Pool:
    def __init__(self, x, y):
        self.turtle = Turtle(x)
        self.fish = Fish(y)

    def print_num(self):
        print("水池有乌龟%s只,鱼%d条!" % (self.turtle.num, self.fish.num))

类定义、类对象和实例对象

  • 类定义是静态的、类对象和实例对象是动态的
  • 使用del销毁类定义后,已存在的类对象和实例对象仍可正常活动,但无法再次通过类定义实例化对象
  • 类定义()实例出来的是类对象,一旦类对象的成员被改动,则变为实例对象。
  • 可通过【类.成员名】的方式影响【类对象的成员】,而不影响【实例对象的成员】

以下是我的个人猜测,如有学友知悉请告知

上栗子,疑惑点不难看出在C.count += 100后,为什么影响到了实例对象a和b的count,而又不会影响到c实例对象呢?通过观察发现c.count被修改了,导致c.count没有被C.count影响(C是类,也是类对象),而其他2个a和b的count依然保持着不被修改过的迹象,所以就会被类对象C影响?

有点类似C#的string的不可变性,比如说,a,b,c在刚开始实例化出来时,它们其实都只是指向同一个初始态实例对象,当c的成员被修改时,c就指向了新的实例对象,而C.count修改的是初始态实例对象,也就是a和b还指向的实例对象,而c自然就没受到影响了。【待确认,疑惑点①】

上栗子,c.x修改后会覆盖掉原本的c.x方法变成一个int类型变量。

绑定

Python严格要求方法需要有实例才能被调用,这种限制其实就是Python所谓的绑定概念。

上栗子,没有给B的printB方法绑定self(即方法第一个参数没有是self)

可通过访问__dict__属性来查看实例对象或类的成员字典

销毁类del

使用del方法销毁

上栗子,虽然我销毁了C类,无法创建新的C类对象,但c对象仍然可正常使用。

类相关内置方法

issubclass(classA, classB)

判断classA是否为classB的子类,若是返回True,否则False

isinstance(obj, class)

判断obj是否为class类的对象

class也可以是一个class元组,只要obj属于元组其中一个class对象就返回True

hasattr(object, name)

判断对象内是否存在属性

getattr(obj, name [, default])

获取对象的一个属性

setattr(obj, name, value)

给对象属性赋值,若没有属性则会新建一个属性赋值

delattr(obj, name)

删除对象内的一个属性,注意:若不存在会引发异常AttributeError,可先检查存在再进行删除。

property(fget=None, fset=None, fdel=None, doc=None)

property(...)将与一个属性相关的3个方法(获取,修改,删除)与x属性绑定,由x属性直接操作size,例如:c1.x=18 就相当于c1.setSize(18) 其他操作同理。

总结

猜你喜欢

转载自blog.csdn.net/qq_39574690/article/details/111561470