类与对象内置的一些装饰器及功能
property:通常配合隐藏属性一起使用
classmethod:绑定给类的方法,绑定给类的,无论谁来调用都会自动传入类
staticmethod:没有跟任何类和对象进行绑定,谁来调用都是一个普通函数
一切皆对象代码原理
class Student:
n = 0
def __init__(self, name, age, gender):
Student.n += 1
self.name = name
self.age = age
self.gender = gender
def choose(self): # self = obj1
print("hello %s" % self.name)
obj1 = Student("nana", 18, "female")
print(type(obj1))
print(Student)
print(obj1.__dict__)
obj1.choose() #对象调函数传参
Student.choose(obj1) #类调函数传参
内置类=内置类型
print(list)
l1 = list([1, 2, 3])
print(type(l1))
print(l1)
l1.append(4) #[1, 2, 3, 4]
list.append(l1, 4) # [1, 2, 3, 4]
装饰器:property
property:通常配合隐藏属性一起使用,被property装饰过的函数可以将功能属性的函数直接伪装成数据属性的函数
class People:
def __init__(self, name, weight, height):
self.name = name
self.weight = weight
self.height = height
@property #被property装饰过的函数可以不用再加()运行,直接将bmi伪装成数据属性的函数
def bmi(self):
return self.weight / (self.height ** 2)
p1 = People("dada", 75, 1.8)
print(p1.bmi)
同一个属性没有增加,可以删改查
class People:
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter # 函数名.setter装饰过的函数,可以直接修改形参x.可以直接写成p1.name="lala")
def name(self, x):
if type(x) is not str:
raise Exception("名字必须是字符串类型") # raise Exception主动抛出异常
self.__name = x
@name.deleter
def name(self):
print("不允许删除")
p1 = People("nana")
print(p1.name) # 调用查看名字的接口
p1.name = "lala" # 调用修改名字的接口
print(p1.name)
del p1.name # 调用删除接口
print(p1.name)
写法二:
class People:
def __init__(self, name):
self.__name = name
def get_name(self):
return self.__name
def set_name(self, x):
if type(x) is not str:
raise Exception("名字必须是字符串类型") # raise Exception主动抛出异常
self.__name = x
def del_name(self):
print("不允许删除")
name = property(get_name, set_name, del_name)
p1 = People("nana") # 调用查看名字的接口
print(p1.name)
p1.name = "lala" # 调用修改名字的接口
print(p1.name)
del p1.name # 调用删除接口
绑定方法与非绑定方法
绑定方法
特点:绑定给谁就应该由谁来调用,谁来调用就会将自己当作第一个参数传入
非绑定方法
特点:不与类和对象绑定,意味着谁都可以来调用,但无论谁来调用就是一个普通函数,没有自动传参的效果
class People:
def __init__(self, name):
self.name = name
# 但凡在类中定义一个函数,默认就是绑定给对象的,应该由对象来调用,
# 会将对象当作第一个参数自动传入
def tell(self):
print(self.name)
# 类中定义的函数被classmethod装饰过,就绑定给类,应该由类来调用
# 类调用会将类本身当作第一个参数自动传入
@classmethod # classmethod会将函数f1绑定给类People
def f1(cls): # cls=People
print(cls)
# 类中定义的函数被staticmethod装饰过,就成了一个非绑定的方法即一个普通函数,谁都可以调用
# 但无论谁来调用就是一个普通函数,没有自动传参的效果
@staticmethod # staticmethod会将函数f2变成非绑定方法的普通函数
def f2(x, y):
print(x, y)
p1 = People("nana")
p1.tell()
print(People.f1) # 打印结果显示为一个绑定方法<bound method People.f1 of <class '__main__.People'>>
People.f1()
People.f2(1, 2)
p1.f2(3, 4)
装饰器的案例使用场景
import setting
class People:
def __init__(self, name, age, gender):
self.id = self.creat_id()
self.name = name
self.age = age
self.gender = gender
def tell_info(self):
print(self.name, self.age, self.gender)
@classmethod # 绑定给类的方法应该由类去调用,如果对象去调用还是会自动传入类的参数
def from_conf(cls): # 导入模块setting,从配置文件读取文件完成实例化
return cls(setting.name, setting.age, setting.gender)
@staticmethod # 非绑定方法
def creat_id():
import uuid
return uuid.uuid1()
p1 = People("lala", 18, "male")
p2 = People.from_conf()
print(p2.__dict__)
print(p1.creat_id())
print(People.creat_id())
print(p1.__dict__)
继承
继承是创建新类的一种方式
新建的类称为子类
被继承的类称为父类,基类,超类
继承的特点是:子类可以遗传父类的属性
类是用来解决对象之间冗余问题的
而继承则是来解决类与类之间冗余问题的
继承具有耦合的特性,与面向对象扩展性的强的特性是相悖的,用继承需要慎用
新式类与经典类
但凡是继承了object类的子类以及该子类的子子孙孙类都是新式类
反之就是经典类
在python2中有新式类与经典类之分,在python3中默认全是新式类
如果在python2中把经典类改成新式类,需要在类名称的后面加(object)
在python中支持多继承
class Parent1:
pass
class Parent2:
pass
class Sub1(Parent1):
pass
class Sub2(Parent1, Parent2):
pass
print(Sub1.__bases__) # (<class '__main__.Parent1'>,)
print(Sub2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
print(Parent1.__bases__) # (<class 'object'>,)
print(Parent2.__bases__) # (<class 'object'>,)
先抽象,再继承
继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承
抽象即抽取类似或者说比较像的部分。
抽象分成两个层次:
1.将奥巴马和梅西这俩对象比较像的部分抽取成类;
2.将人,猪,狗这三个类比较像的部分抽取成父类。
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到类
继承背景下的属性查找
继承背景下的属性查找的顺序:先从对象里面找,如果对象里面没有,再从类里面查找,如果类里面也没有,再从父类里面找
class Bar: # Bar的父类不写默认是object
y = 666
class Foo(Bar):
def __init__(self, x):
self.x = x
obj = Foo(111)
print(obj.__dict__)
print(obj.x)
print(obj.y)
示例一:
class Bar:
def f1(self):
print("Bar.f1")
def f2(self):
print("Bar.f2")
self.f1() # obj.f1()
class Foo(Bar):
def f1(self):
print("Foo.f1")
obj = Foo() # Foo.f1
obj.f2() # Bar.f2
示例二:
class Bar:
def __f1(self): # _Bar__f1
print("Bar.f1")
def f2(self):
print("Bar.f2")
self.__f1() # _Bar__f1
class Foo(Bar):
def __f1(self): # _Foo__f1
print("Foo.f1")
obj = Foo() # Bar.f1
obj.f2() # Bar.f2