面向对象2
回顾类的创建
class p1(): #定义类
pass
class p2():
pass
p1=p1()#实例化
p2=p2()#实例化
print(p1)
print(p2).
实例变量:在所有类的所有方法,都可以访问到
局部变量:在函数里面有效,出了函数就不可以使用。
"""
类:
可以把数据封装在类的实例里面去管理,
使用类里面的实例方法来管理这些数据,保证数据的安全性
类里面要有数据,还有操作数据的方法(设定操作数据的规则)
"""
person = [["wulaoshi",10],["lilaoshi",20]]
person[1][1] = -10
print(person)
结果显示:
D:\>py b.py
[['wulaoshi', 10], ['lilaoshi', -10]]
结果很容易被改而形成脏数据,无意中更改后就没有办法使用
根据类中方法set_age方法校验传参
class Person:
def __init__(self,name,age):
if isinstance(age,int) and age > 0:
self.age = age
else:
self.age = 0
self.name = name
def set_age(self,age):
if isinstance(age,int) and age > 0: #根据传参判断是否符合要求;
self.age = age
def get_age(self):
return self.age
p1=Person("wulaoshi",18) #实例化
p2=Person("lilaoshi",28) #实例化
print(p1.age)
print(p2.age)
p1.set_age(-1) #通过访问set_age方法进行修改参数;
print(p1.age)
结果输出
D:\>py b.py
18
28
18 #不符合set_age规则,没有修改成功;
根据私有变量self.__age防止传入外部传入脏数据
class Person:
def __init__(self,name,age):
if isinstance(age,int) and age > 0:
self.__age = age #self.__age私有变量
else:
self.__age = 0 #self.__age私有变量
self.name = name
def set_age(self,age):
if isinstance(age,int) and age > 0:
self.__age = age #self.__age私有变量
def get_age(self):
return self.__age #self.__age私有变量
p1=Person("wulaoshi",18)
p2=Person("lilaoshi",28)
p1.__age = -1 #直接修改私有变量
print(p1.__age)
结果输出
D:\>py b.py
Traceback (most recent call last):
File "b.py", line 27, in <module>
print(p1.age)
AttributeError: 'Person' object has no attribute 'age' #结果返回对象没有age属性
新变量p1.__age = -100与类中私有变量无关
class Person:
def __init__(self,name,age):
if isinstance(age,int) and age > 0:
self.__age = age
else:
self.__age = 0
self.name = name
def set_age(self,age):
if isinstance(age,int) and age > 0:
self.__age = age
def get_age(self):
return self.__age
p1=Person("wulaoshi",18)
p2=Person("lilaoshi",28)
p1.__age = -100 #新变量,不是类中的私有变量
print(p1.__age) #打印的也是新的变量值
print(p1.get_age()) #验证,私有变量未被改变
结果输出
D:\>py b.py
-100 #返回新变量的值
18 #返回私有变量的值,结果未改变类中私有变量的值
私有方法__print__age
class Person:
def __init__(self,name,age):
if isinstance(age,int) and age > 0:
self.__age = age
else:
self.__age = 0
self.name = name #self.name实例变量,name局部变量
def set_age(self,age):
if isinstance(age,int) and age > 0:
self.__age = age
def __print__age(self): #私有方法
print(self.__age)
def get_age(self):
self.__print__age() #通过其类当中他方法访问私有方法
return self.__age
p1=Person("wulaoshi",18)
p2=Person("lilaoshi",28)
p1.get_age() #通过类当中其他方法进行访问私有方法
结果输出
D:\>py b.py
18
p1.__print_age() #不能直接访问私有方法
结果输出
D:\>py b.py
Traceback (most recent call last):
File "b.py", line 30, in <module>
p1.__print_age()
AttributeError: 'Person' object has no attribute '__print_age'
self.name实例变量:在所有类的所有方法,都可以访问到
name局部变量:在函数里面有效,出了函数就不可以使用。
类的函数:
>>> class P:
... pass
...
>>> p=P()
>>> dir(p)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> p.__class__
<class '__main__.P'>
内存解释:
class Person:
def __init__(self,name):
self.name = name
def get_name(self):
print(self.name)
def get_name2(self):
print(self.name,self.name)
p1=Person("wulaoshi") #mmmzzz2
p1.get_name() #self就是p1的内存地址
p1.get_name2() #self就是p1的内存地址
p2=Person("李老师") #mmmzzz3
p2.get_name() #self就是p2的内存地址
p2.get_name2() #self就是p2的内存地址
内存:
类Person放在内存地址:xxxyyy1
get_name():这个方法的调用要有一个self参数
实例p1放在内存地址:mmmmzzz2
name="wulaoshi"
p1.get_name()的调用过程:
1)在xxxyyy1中先把get_name()的内容找出来
想去调用。当去调用的时候发现get_name()里面有个self
2)实例变量p1的内存地址 p1---> self=mmmmzzz2 传给 get_name() 这个方法
3)get_name(self=mmmmzzz2)
4)执行函数(方法体)内部的时候:print(self.name)
5)去mmmmzzz2找到name的值,然后打印,完成。
6)完成
Self的工作原理:
1)self是通过把实例的内存地址传递个方法内部,方法内部通过实例地址可以找到你想要的实例任何数据
2)类中的实例方法中的第一个参数self,实际就是实例所在的地址,通过这个地址,可以找到实例方法中需要使用的各种实例属性(数据)
类变量
"""
类内存:
存类的方法 #内存储的东西全局只有一份
类变量:谁都可以对它做修改,但是所有人读的值都是一样的
类变量是放在方法外面的,一般情况下是用在计算实例创建的数量
"""
class Person:
x=0 #类变量
def __init__(self,name): #只有在实例化的时候才可以调用__init__的方法
self.name = name
Person.x+=1 #方法内使用类变量需要加上类的名字Person.x
def get_name(self):
print(self.name)
p1=Person("wulaoshi") #实例化:类名+()+参数
p2=Person("lilaoshi")
print(Person.x) #访问类变量
print(p1.x) #也可以使用实例访问,返回的值是一样
print(p2.x)
实例化:p1=Person("wulaoshi")
实例对象:p1
实例方法:get_name
实例变量:self.name
继承、
class Person:
def __init__(self,name):
self.name = name
def set_name(self,name):
self.name = name
def get_name(self):
return self.name
class AsianPerson(Person): #(Person)是AsianPerson父类
def __init__(self,name,nation):
Person.__init__(self,name) #必须填写
self.name = name # 可以不写self.name = name,
因为基于Person父类可以直接调用
self.nation = nation
def set_nation(self,nation):
self.nation = nation
def get_nation(self):
return self.nation
ap= AsianPerson("laowang","china")
print(ap.get_name())
print(ap.get_nation())
ap.set_name("laolaowang")
print(ap.get_name())
p=Person("老李") #创建父类实例调用的还是父类方法。
print(p.get_name())
#(Person)是AsianPerson父类,Person所有的方法AsianPerson都可以使用,基于原有的内容来做扩展
关于Person.__init__(self,name)的使用
class Person:
def __init__(self,name):
self.name = name
def set_name(self,name):
self.name = name
def get_name(self):
return self.name
class AsianPerson(Person): #(Person)是AsianPerson父类
def __init__(self,name,nation):
#Person.__init__(self,name) #因为没有使用父类的构造方法来把那name做初始化,所有想直接使用这个self.name就会失败。
self.nation = nation
def set_nation(self,nation):
self.nation = nation
def get_nation(self):
return self.nation
ap= AsianPerson("laowang","china") #单独写不会报错
print(ap.name()) #打印会报没有name属性
使用Person.__init__(self,name) 可以调用Person全部的方法
- 子类想使用父类的方法。变量,则必须在
- 子类的构造函数中来完成父类实例的构造方法调用
示例:
class AsianPerson(Person):
def __init__(self,name,nation):
Person.__init__(self,name)
- 私有方法和私有属性无法继承(不能直接使用,可以使用父类本身具有的方法继续操作),只能使用公用的方法和属性
- 父类的__init__构造函数,是不会被子类继承的
- 父类其他的公有变量和公有方法,可以被子类继承
class Person:
def __init__(self,name):
self.name = name
def set_name(self,name):
self.name = name
def get_name(self):
return self.name
class AsianPerson(Person): #(Person)是AsianPerson父类
def __init__(self,name,nation):
Person.__init__(self,name)
self.nation = nation
def get_name(self): #重写了父类中的方法
return "***:"+self.name
ap= AsianPerson("laowang","china")
print(ap.get_name()) #只会调用子类
def get_name(self): #重写了父类中的方法
return "***:"+super().get_name() #表示在get_name方法里面调用了一下父类的get_name方法
执行结果:
D:\>py b.py
***:laowang
def get_name(self): #重写了父类中的方法
return "***:"+super().get_name() #表示在get_name方法里面调用了一下父类的get_name方法
ap= AsianPerson("laowang","china")
print(ap.get_name()) #只会调用子类
执行结果:
D:\>py b.py
***:laowang # 使用super().get_name()执行结果与上面一致
指令调用父类方法super().get_name()
重写:把父类的方法覆盖掉,使用子类的同名方法
重载:多个方法名一样,但是他们的参数类型,
还有参数个数不一样(针对java);
Python不支持重载
调用父类的方法(三种):
1)super().get_name()
2)return "***:"+Person.get_name(self)
3)super(AsianPerson,self).get_name()
父类中有操作私有变量的方法,子类可以操作父类的方法使用
class Person:
def __init__(self,name):
self.__name = name
def set_name(self,name): #父类本身具备修改私有变量的方法
self.__name = name
def get_name(self):
return self.__name
class AsianPerson(Person): #(Person)是AsianPerson父类
def __init__(self,name,nation):
Person.__init__(self,name)
self.nation = nation
ap= AsianPerson("laowang","china")
print(ap.get_name()) #只会调用子类
print(ap.set_name("laoli")) #通过操作父类方法修改变量
print(ap.get_name()) #返回修改后的结果
返回结果
D:\>py b.py
laowang
None
laoli #成功修改
私有变量不能直接访问或重写
class Person:
def __init__(self,name):
self.__name = name
def set_name(self,name):
self.__name = name
def get_name(self):
return self.__name
class AsianPerson(Person): #(Person)是AsianPerson父类
def __init__(self,name,nation):
Person.__init__(self)
self.nation = nation
def get_name(self): #重写父类中的私有变量
return self.__name #父类中存在这种私有变量,子类不允许重写和访问
ap= AsianPerson("laowang","china")
print(ap.get_name()) #不能读取私有变量
返回结果:
D:\>py b.py
Traceback (most recent call last):
File "b.py", line 20, in <module>
ap= AsianPerson("laowang","china")
File "b.py", line 14, in __init__
Person.__init__(self)
TypeError: __init__() missing 1 required positional argument: 'name'
如果父类中有私有变量,那么子类的方法是不能读取父类中的私有变量