目录
__init__(self, param1, param2...)
getattr(obj, name [, default])
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) 其他操作同理。