Python面向对象
Python面向对象
每次默认调用的方法是new,程序先调new再掉init
init可以完成参数赋值等一些基本的初始化工作
init和new的参数要保持一致
创建与删除对象
init 创建对象
当创建一个对象时,python解释器默认会调用一个方法,这个方法是: __init__()
#给定默认值 xxxx 21
def __init__(self,name="xxxx",age=21):
def __init__(self,*args,**kwargs):
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def run(self):
# print("persion is running")
print("%s is running" %self.name)
p = Person("zhangsan",18)
p.run()
class Animal:
# 对象初始化时调用
def __init__(self,name):
self.name = name
print(self.name+"来了")
# 创建对象,初始化 init方法调用
an = Animal("唐僧")
new 构造器
构造器__new__ 构造器中的参数要和init中的参数一样,换而言之,无论什么情况init和new参数保持一致
一定要有返回值
def __init__(self,name,age):
self.name = name
self.age = age
def __new__(cls,name,age):
cls.name = name
cls.age = age
return object.__new__(cls)
del 删除
调用:
当删除一个对象时,
python解释器也会调用一个方法,这个方法是: __del__()
最后释放内存时调用
若多个对象n指向同一个类,则此时计数器的个数为n.
每次调用del方法时删除的是计数器的个数(n-1),也就是说每调用一次del就删除一下,计数器总个数-1
若计数器为1时再调用,则删除该对象案例:
class Animal:
# 对象被回收时调用
def __del__(self):
print(self.name+"被妖怪抓走了")
手动删除对象,之后将不能在被使用,如果使用会报错
del an
print(an.name)
如果没有手动删除,对象将在使用完才被系统收走
案例:
# 创建对象,初始化 init方法调用
an = Animal("唐僧")
# 手动删除对象,之后将不能在被使用,如果使用会报错
an1 = an
an2 = an
print(id(an))
print(id(an1))
print(id(an2))
print("马上删除对象an")
del an
print("马上删除对象an1")
del an1
print("马上删除对象an2")
# 这句代码执行完毕,对象才会被真正删除(引用计数)
del an2
引用计数:
刚创建出来的时候为2,增加一个引用,引用计数+1,
del 对象 ,可以减少引用计数,当引用计
数为1时,在del 对象,才会真正被回收
魔法方法1—id
类似于java内存地址的值,用于判断对象是否是单例模式
#此时ip一样 #此时id不一样
p1 = person(xxxxxxxx) p1 = persion(xxxxxx)
p2 = p1 p2 = persion(xxxxxx)
print(id(p1)) print(id(p1))
print(id(p2)) print(id(p2))
魔法方法2—str
类似于java的toString打印的方法
共有/私有转换
# 私有方法
def test(self):
print("调用test共有方法")
继承
单继承
继承概念
用来描述类与类之间的一种关系:
父类、超类、基类
子类、派生类
继承的语法
class 子类(父类名,...):
方法...
如果一个类没有明确指明父类,则它的父类为object
案例:
- 定义Cat类,包含属性: name,color,age;方法:eat() sleep() catchmouse()
- 定义Dog类,包含属性: nage,color,age;方法:eat() sleep() lookafterHouse()
- 发现许多重复的东西,优化,抽离一个父类Animal出来
总结:
- 子类可以继承父类中所有的属性跟方法(私有除外)
- 私有属性不能通过对象直接访问,但可以通过方法访问
- 私有方法,不能通过对象直接访问
属性自动化赋值(高级用法)(setattr,getattr,hasattr,isinstance函数的使用)
# 属性自动化赋值
class Dog():
def __init__(self,name,age,gender,color,breed):
print(locals())
# pass
self.attributeFromdict(locals())
# 自定义方法,设置属性
def attributeFromdict(self,d):
self = d.pop('self')
for n, v in d.items():
# 内置函数,为self的属性赋值value
setattr(self,n,v)
def showinfo(self):
print(self.name)
print(self.age)
print(self.breed)
print(self.gender)
dog =Dog('aa',12,'男','red','京巴')
dog.showinfo()
多继承
概念
所谓多继承,就是一个类同时有多个父类
思考:狼狗的父类
狼、狗
语法
class 子类(父类1,父类2):
方法...
如果父类1,父类2中都有属性,则以先继承的类为标准,如果两个父类存在同名方法,则一样
以先继承的类为准,所有父类中的非同名方法都能被继承到
若父类都有相同名的方法,则先调用(xx,oo)括号里前面的父类方法
两个父类中的方法,属性,都会被子类继承
class AAA():
def methodAAA(self):
print("a的方法a")
# 新增方法,BBB类中有同名方法
def methodBBB(self):
print("a的方法b")
class BBB():
def methodBBB(self):
print("b的方法b")
class CCC(AAA,BBB):
def methodCCC(self):
self.methodAAA()
self.methodBBB()
print("c的方法c")
ccc = CCC()
ccc.methodCCC()
# 执行结果
# a的方法a
# a的方法b
# c的方法c
重写
重写父类的方法与调用父类的方法
方法重写概念:
所谓重写,就是在子类中,有一个和父类相同名字的方法,子类中的方法会覆盖掉父类中的同名方法
方法重写案例:
class SuperClass():
def __init__(self):
print("父类的初始化方法")
def test(self):
print("父类的测试方法")
class SubClass(SuperClass):
def __init__(self):
print("子类的初始化方法")
def test(self):
print("子类的测试方法")
sub = SubClass()
# 这里的test方法,调用的为子类中重写的方法
sub.test()
# 执行结果
# 子类的初始化方法
# 子类的测试方法
调用父类方法:
class Cat(Animal,Active):
#1 super().__init__(name)
#2 Animal.__init__(self,name)
class SuperClass():
def __init__(self,name):
self.name = name
def test(self):
print("父类的测试方法")
class SubClass(SuperClass):
def __init__(self,name,age):
# SuperClass.__init__(self,name)
super(SubClass, self).init(name)
super().init(name)
self.age = age
# 子类重写父类方法
def test(self):
print("子类的测试方法")
print('name:'+self.name+",age:"+str(self.age))
sub = SubClass(‘aa’,12)
sub.test()执行结果
子类的测试方法
name:aa,age:12
多态
概念
- 定义时的类型跟运行时的类型不一样,此时就成为多态
严格意义上来讲,python中的多态不叫真正的多态,称之为鸭子类型更合适 鸭子类型
“鸭子类型”的语言是这么推断的:一只鸟走起来像鸭子、游起泳来像鸭子、叫起来也像鸭子,
那它就可以被当做鸭子。也就是说,它不关注对象的类型,而是关注对象具有的行为(方法)。鸭子类型弊端
“鸭子类型”语言的程序可能会在运行时因为不具备某种特定的方法而抛出异常:
案例1:
如果一只小狗(对象)想加入合唱团(以对象会不会嘎嘎嘎叫的方法为检验标准),
也学鸭子那么嘎嘎嘎叫,好吧,它加入了,可是加入之后,却不会像鸭子那样走路,
那么,迟早要出问题的。案例2:
一只小老鼠被猫盯上了,情急之下,它学了狗叫,猫撤了之后,小老鼠的妈妈不无感叹的
对它说:看吧,我让你学的这门儿外语多么重要啊。这虽然是个段子,但是,由于猫在
思考时,使用了 “鸭子测试”,它以为会叫的就是狗,会对自己产生威胁,所以撤退了,
也正是因为这个错误的判断,它误失了一次进食机会。
- 定义时的类型跟运行时的类型不一样,此时就成为多态
用法
class F1(object):
def show(self):
print("F1.show")
class S1(F1):
def show(self):
print("S1.show")
class S2(S1):
def show(self):
print("S2.show")
def func(obj):
obj.show()
obj1 = F1()
func(obj1)
obj1 = S1()
func(obj1)
obj1 = S2()
func(obj1)
类属性、实例属性
类属性:class内,方法外
实例属性:方法内
类属性
属于类对象所拥有的属性,它被所有类对象的实例对象所公有,在内存中只有一份
类属性的访问方式
在类外可以通过类名访问
类名.属性名
在类外可以通过实例对象访问
对象名.属性名
案例:
class Student:
# 类属性
schoolName="湖南"
def __init__(self,name,age):
# 实例属性
self.name = name
self.age = age
st1 = Student(‘陈独秀’,29)
通过类名访问类属性
print(Student.schoolName)
通过对象访问类属性
print(st1.schoolName)
通过对象访问修改属性,会新增对象属性,之后通过对象访问类属性将无法访问到,因为会被新增的对象属性屏蔽
st1.schoolName = ‘京南校区’
类属性访问结果不变
print(Student.schoolName)
这只能访问到对象属性
print(st1.schoolName)
可以手动删除新增的对象属性
del st1.schoolName
因为对象属性被删除,所以,这访问的依旧是类属性
print(st1.schoolName)
静态方法和类方法
类方法 @classmethod 实例属性+ @classmethod 变成类属性
- 概念
是类对象所拥有的方法,需要用 @classmethod 来表示,类方法第一个参数必须为类对象
一般使用’cls’, 类方法能够通过类名和对象进行访问用法:
class Student:类属性
schoolName=“湖南”
def init(self,name,age):
# 实例属性
self.name = name
self.age = age类方法 (可以直接访问类属性,因此get方法中不能有self关键字,要用cls)
@classmethod
def getSchoolName(cls):
return cls.schoolName@classmethod
def setSchoolName(cls,newSchoolName):
cls.schoolName = newSchoolName
st2 = Student(‘李大钊’,30)
Student.schoolName = ‘北平学校’通过对象访问类方法
print(st2.getSchoolName())
通过类名方法类方法(使用较多)
print(Student.getSchoolName())
Student.setSchoolName(‘同济学校’)
print(Student.getSchoolName())
注意: 类方法中可以直接修改当前类的类属性静态方法 @staticmethod
概念
需要使用 @staticmethod 进行修饰,静态方法不需要定义参数
用法
可以访问类属性,但是必须通过类名,
调用方式:可以通过类名,对象进行调用
class Student:# 类属性
schoolName="湖南"
def __init__(self,name,age):
# 实例属性
self.name = name
self.age = age
# 静态方法 (可以通过类名访问类属性)
@staticmethod
def getSchoolName():
return Student.schoolName
Tips:
- 成员属性、类属性、私有属性
- 成员方法、类方法、静态方法、私有方法
还没有评论,来说两句吧...