- 对象是把数据与功能整合到一起的产物,或者说对象就是一个盛放数据与功能的容器
- 类是用来存放多个对象相同的数据与功能的容器,是一种节省空间、减少冗余代码的机制,面向对象编程最终的核心仍然是去使用对象
- 类体的代码在类定义阶段就会执行,所以会产生新的名称空间来存放类中定义的名字。
-
class Student:
school = '清华大学'
# __init__方法会在对象产生之后自动执行,专门为对象进行初始化操作,可以有任意代码,但是必须得返回None或者不写也是返回None
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
# return '1'
def choose(self):
print('%s is chooseing a course' %self.name)
print(Student.__dict__)
stu1 = Student('张三','男',12)
stu2 = Student('李四','女',24)
stu3 = Student('王五','男',36)
print(stu1.__dict__)
print(Student.__dict__['school']) # 这种访问方式过于繁琐
print(Student.school)
stu1.choose()
print(id(Student.choose))
print(id(stu1.choose))
print(id(stu2.choose))
print(id(stu3.choose))
print(stu1.choose)
print(stu2.choose)
print(stu3.choose)
stu1.choose()
stu2.choose()
stu3.choose()
print(list)
-
class Foo:
__N = 0
def __init__(self):
self.__x = 10
def __f1(self):
print('__f1 run')
def __f2(self):
self.__f1()
# print(Foo.__N)
print(Foo._Foo__N)
obj = Foo()
print(obj._Foo__x)
Foo._Foo__f1(obj)
Foo._Foo__f2(obj)
Foo.__N = 100
print(Foo.__N)
-
class Teacher:
def __init__(self, name=None, age=0):
# 姓名、年龄对外设置隐藏
self.__name = name
self.__age = age
# 隐藏并不是目的要对外提供可访问的接口
def tell_info(self):
print('我的姓名是%s,我的年龄是%s' %(self.__name,self.__age))
# 允许外部对老师的姓名年龄进行设置
def set_info(self,name,age):
if not isinstance(name,str):
raise TypeError('姓名必须是字符串类型')
if not isinstance(age,int):
raise TypeError('年龄必须是整数类型')
self.__name = name
self.__age = age
t = Teacher('张三',23)
t.tell_info()
t1 = Teacher()
t1.set_info('里斯',24)
# t1.set_info('里斯','24')
# t1.set_info(23,'24')
t1.tell_info()
-
>>> class ATM:
... def __card(self): #插卡
... print('插卡')
... def __auth(self): #身份认证
... print('用户认证')
... def __input(self): #输入金额
... print('输入取款金额')
... def __print_bill(self): #打印小票
... print('打印账单')
... def __take_money(self): #取钱
... print('取款')
... def withdraw(self): #取款功能
... self.__card()
... self.__auth()
... self.__input()
... self.__print_bill()
... self.__take_money()
...
>>> obj=ATM()
>>> obj.withdraw()
- Python提供了一个装饰器property,可以将类中的函数"伪装"成对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果
>>> class People:
... def __init__(self,name,weight,height):
... self.name=name
... self.weight=weight
... self.height=height
... @property
... def bmi(self):
... return self.weight / (self.height**2)
...
>>> obj=People('lili',75,1.85)
>>> obj.bmi #触发方法bmi的执行,将obj自动传给self,执行后返回值作为本次引用的结果
21.913805697589478
- 查看该类的所有父类
#!/usr/bin/env python
#author:lijipeng
class Parent1:
pass
class Parent2:
pass
class Son1(Parent1,Parent2):
pass
print(Son1.__bases__)
- 经典类:没有显示的继承object类的类,以及该类的子类
- 新式类:显示的继承object类的类,以及该类的子类
- Python3中没有新式类和经典类之分,因为没有显示继承也会默认继承object类
- 总结对象与对象之间的相似关系可以得到类,总结类与类之间的相似关系可以得到父类
- 继承可以解决类与类之间代码重用的问题
-
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1()
class Bar(Foo):
def f1(self):
print('Bar.f1')
b = Bar()
b.f2()
- 如果父类不想让子类覆盖自己的方法,可以采用双下划线开头的方式将方法设置为私有
class Foo:
def f1(self):
print('Foo.f1')
def __f2(self):
print('Foo.f2')
self.f1()
class Bar(Foo):
def f1(self):
print('Bar.f1')
b = Bar()
b.f2()
- 类有一个mro()方法,它是一个合并了所有父类的MRO列表,且在查找属性时,Python会基于MRO列表按照从左到右的顺序依次查找基类,直到找到第一个匹配这个属性的类为止
- 经典类多继承深度优先,新式类多继承广度优先。
- 重用父类的代码的两种方式:指名道姓、super() 前者跟继承没有关系,后者是依赖于继承的,super()仍然会按照MRO继续往后查找
-
#!/usr/bin/env python
#author:lijipeng
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass
class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
# def talk(self):
# pass
pass
cat=Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
- 鸭子类型在某种程度上实现了程序的松耦合度
- 类中的函数分为两大类:绑定方法,非绑定方法
- 绑定方法又分为绑定到类的方法和绑定到对象的方法
- 类中的函数默认绑定到对象上,函数上面加@classmethod后,该函数就绑定到了类
- 为类中某个函数加上装饰器@staticmethod后,该函数就变成了非绑定方法,也称为静态方法。不与对象和类绑定,都可以来调用它,就是一个普通函数,所以没有自动传值一说。
- 功能实现代码需要引用对象将其定义为对象方法,需要引用类定义为类方法,无需引用类或对象定义为静态方法