保护对象的属性(封装)
如果有一个对象,当需要对其进行修改属性时,有二种方法:
- 对象名.属性名 = 数据 ------>直接修改;
- 对象名.方法名()------->间接修改;
为了更好的保护属性安全,既不能随意修改,一般的处理方式为:
- 将属性定义为私有属性;
- 添加一个可以调用的方法,供调用;
class User:
def __init__(self,pw):
if len(pw) >=6:
self.__password = pw
else:
print("密码:%s,密码不符合规定"%pw)
def __str__(self):
return "密码%s"%self.__password
def get_password(self):
return self.__password
u1 = User("123456")
print(u1.get_password())
print(u1)
123456
密码:123456
__del__( )方法
当创建一个对象后,python解释器默认调用__init__()方法;
当删除一个对象时,python解释器也会默认调用一个方法,即__del__( )方法;
- 当有一个变量保存了对象的引用时,此对象的引用计数就会加1;
- 当使用del删除变量指向的对象时,如果对象的引用计数不是1,比如3.那么此时只会让这个引用计数减1,即变为2,当再次调用del时,变为1,如果再次调用del时,变为1,如果再次调用1次del,此时真的把对象进行删除;
- 当整个程序执行完成之后,此时的对象一定会被删除;
(单)继承
在程序中,继承描述的事物之间的所属关系,例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物;同理,波斯猫和巴厘猫都继承自猫。
class Animal:
def __init__(self):
self.name="动物"
def eat(self):
print("-----吃饭-----")
def sleep(self):
print("-----睡觉-----")
class Dog(Animal):
def __init__(self,name):
self.name=name
def shout(self):
print("-----大叫-----")
class Cat(Animal):
# def __init__(self):
# print("猫初始化了")
def catch(self):
print("-----抓老鼠-----")
class Zangao(Dog):
def fight(self):
print("-----战斗------")
dog = Dog()
dog.eat()
print(dog.name)
#cat = Cat()
#print(cat.name)
za = Zangao()
za.eat()
-----吃饭-----
动物
-----吃饭-----
动物
切记:私有属性不能被继承
多继承
所谓多继承,即子类有多个父类,并且具有它们的特征。
# 定义第一个父类
class A:
def test(self):
print("------A------")
#定义第二个父类
class B:
def test(self):
print("------B------")
#第一个子类
class C(A,B): # A和B写的顺序跟优先级是有关系的
def test1(self):
print("------C-------")
c = C()
print(C.__mro__) #获得多继承的优先级的顺序;
c.test()
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class
'object'>)
------A------
注意:object:默认情况下都一个父类就是object,之前所有的特殊方法都是继承父类object;
重写父类方法与调用父类方法
class Animal:
# 父类定义init方法
def __init__(self):
print("动物初始化了")
self.__name = "动物"
self.color = "yellow"
def eat(self):
print("-----吃饭-----")
def sleep(self):
print("-----睡觉-----")
class Dog(Animal):
# init和父类的init名字一样,所以叫方法的重写
def __init__(self,name):
super().__init() # 主动调用父类的init方法
print("狗被初始化了")
self.name=name
def shout(self):
print("-----大叫-----")
class Cat(Animal):
# 重写父类的init方法
# def __init__(self):
# print("猫初始化了")
def catch(self):
print("-----抓老鼠-----")
class Zangao(Dog):
def fight(self):
print("-----战斗------")
dog = Dog("小白") #如果子类中对某个方法重写了,优先调用子类自己本身的方法
动物初始化了
狗被初始化了
小白
yellow
多态
python是一个弱所谓多态,定义时的类型和运行时的类型不一样,此时就成为多态;python是一个弱语言,所以对于多态表现的不明显。
什么是类属性和实例属性?
在之前的例子中我们接触到的就是实例属性(对象属性),顾名思义,类属性就是类对象所拥有的属性,他被所有类对象的实例对象所共有,在内存中只存在一个副本。对于公有类属性,在类外可以通过类对象和实例对象访问。
# 类属性:所属类,这个类下所有的对象都可以共享这个类属性。
class User():
name ="xihu" # 公共的类属性
__passward = "123456" # 私有的类属性
def __init__(self,sex,username):
self.sex = sex
self.username = username
class WeChat_User(User):
pass
re = User("男","lanjing")
print(re.name)
print(re.sex)
print(re.username)
print(WeChat_User.name)#name从父类继承过来的,name属于类属性。可以直接通过类的对象来访问
print(re.name)
#类属性的修改,只能通过类属性修改
User.name = "xiaoli" #真正的类属性修改
u.name = "xili" #本质上没有修改类属性。仅仅给对象定义了一个对象属性name。并且赋值“xiaoli”
del re.name #本质上删除了对象的name属性,并没有删除类的属性。
xihu
男
lanjing
xihu
xili # 这不是修改类属性name
总结:
如果需要在类外修改类属性,必须通过类对象去引用后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称属性,实例属性会强制屏蔽掉类属性,即引用的实例属性,除非删除了该实例属性。
属性叫法 | 变量叫法 | 描述 |
类属性 | 类变量 | 所有对象共享同一份类属性 |
实例属性 | 成员变量 | 每个不同对象,有不一样值的实例属性 |
定义类方法
class A(object):
name = "zs"
def test1(self):
print("----A 的test1的方法")
@classmethod #类方法一定要在方法上面加一个修饰器,类方法的参数cls,代表当前的类
def test2(cls):
cls.name = "xiaoli"
print("----A 的test2的方法")
@staticmethod#静态方法,属于类。没有默认传递的参数,可以通过类对象来调用,也可以通过类名来调用
def test3():
A.name = "ls"
print("------A的test3静态方法")
a = A()
a.test2()
A.test2()
A.test3()
print(A.name)
----A 的test2的方法
----A 的test2的方法
xiaoli
静态方法
类方法的一种,有专门的修饰器,如上。
总结:
从类方法和实例方法以及静态方法的定义形式就可以看出来,类方法第一个参数是类的对象cls,那么通过cls引用必定是类对象的属性和方法;而实例方法的第一个参数是实例对象self,那么通过self引用的可能是类属性、也可能是实例属性属性(这个需要具体分析),不过在存在相同名称的类属性和实例属性的情况下,实例属性优先等级更高。静态方法中不需要额外定义参数,因此在静态方法中引用类属性的话,必须通过类对象来引用。
方法类名 | 语法 | 描述 |
类方法 | @classmethod | 第一个形参cls,默认传递 |
静态方法 | @staticmethod | 没有默认传递的形参 |
对象方法(成员方法) | def 方法名 | 第一个形参self,默认传递 |
特殊方法名 | 默认参数 | 功能描述 |
_init__() | self | |
__str__() | self | |
__del__() | self | |
__new__() | cls |