面向对象介绍
世界万物,皆可分类,皆为对象,只要是对象,就肯定有种类与属性,把一个类变成 具体对象的过程叫 实例化
class 类
一个类即是一个拥有相同属性和方法的对象模版。是共同属性和方法的集合。
object 对象
用模版生产出来的产品,一个对象就是经过一个类实例化后得到的产物,一个类可以实例化多个对象,每个对象可以有不同的属性,也可以有相同属性
# 模版
class who:
"""创建一个简单的类"""
def __init__(self,name):
self.name = name #实例变量(静态属性)
def call(self): #类的方法(动态属性)
print("%s在叫"%self.name)
# 实例化的对象
dog = who("狗") #实例对象
dog.call() # who.call(dog) #狗在叫
# dog.name = "asdf" #可增删改查
# dog.call()
c = who("猫")
c.call() #猫在叫
类的实例化
单独开个空间存放(把类赋值给一个变量所生成的对象)类的实例化会调用的 def
__init__(self)
构造函数,参数可以有多个,但是第一个位置必须是self,
self
代表实例本身
self
相当于def __init__(dog.name) def call(dog)
构造函数def __init__(self):
在实例化时做一些类的初始化的工作
变量
类变量---->所有实例共用的变量,节省开销
实例属性 :
静态属性----> 作用域为实例本身
动态属性----> 类的方法
私有属性----> 也是私有变量,在变量名前加上 _ _ 内部可以被修改与调用,在外部访问不了
私有方法---->私有方法和私有属性相同 在方法名前面加上 _ _内部可以被修改与调用,在外部访问不了
class who: """私有属性,私有方法""" def __init__(self,name,age=5): self.name = name #实例变量(静态属性) self.__age = age #私有变量 def __h(self): #私有方法 print("私有方法") def l(self): #类的方法(动态属性) self.__age = 20 #只有内部可以被修改 self.__h() #只有内部可以被调用 print("%s现在%s岁"%(self.name,self.__age)) a = who("你") a.l() """结果 私有方法 你现在20岁 """
析构函数def __del__(self):
程序退出、实例释放、销毁的时候自动执行的,通常用于做一些收尾工作,通常用于做一些收尾工作,如关闭一些数据库连接,关闭打开的临时文件
class a:
def __init__(self,name):
self.name = name
def __del__(self):
print("自动运行析构函数")
def b1(self):
print("%s运行方法"%self.name)
c = a("你在")
"""结果
自动运行析构函数"""
三大特性
Encapsulation封装
相当于一个人,看不到里面的器官,把类中的数据把包成一个容器,对外只可看到一些接口,通过接口进行访问对象
Inheritance继承
可从父类继承一些定义的属性与方法,从而简化代码,python3是统一按广度优先来继承的,python2经典类是按深度优先来继承的,新式类是按广度优先来继承的
class Phones_1(object): #新式类写法
"""父类_1"""
def __init__(self,name,cpu):
self.name = name
self.cpu = cpu
self.f = [] #```
def parameter(self):
print("%s手机的cpu%s"%(self.name,self.cpu))
class Phones_2(object):
"""父类_2"""
def call(self,obj): #huawei.call(miui) 这里传入miui,所以obj就是miui
print("%s和%s配置差不多"%(self.name,obj.name)) # self.name 没出错是因为在子类以经进行了重构
self.f.append(obj) #```
class Cell_1(Phones_1,Phones_2): #继承父类 多继承
"""子类_1"""
def __init__(self,name,cpu,money): #进行重构,增加一个 money属性
#phones_1.__init__(self, name,cpu) #调用父类 旧时代写法
super(Cell_1, self).__init__(name, cpu) # 新式类写法 和phones_1.__init__(self, name,cpu)一样,好处是phones改变,也可以用
self.money = money
def parameter(self): #重构父类方法
#phones_1.parameter(self) #调用父类的方法 旧时代写法
super(Cell_1, self).parameter() #调用父类的方法
print("%s这个月发行的新产品:%s"%(self.name,self.money)) #给子类增加新功能
class Cell_2(Phones_1):
"""子类_2"""
def products(self):
print("出售产品是%s"%self.name)
huawei = Cell_1("p50","高通855",5000)
huawei.parameter()
miui = Cell_2("小米10",845)
miui.parameter()
miui.products()
huawei.call(miui)
print(huawei.f[0].name)
"""p50手机的cpu高通855
p50这个月发行的新产品:5000
小米10手机的cpu845
出售产品是小米10
p50和小米10配置差不多
小米10"""
Polymorphism多态
”一个接口多种实现“,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
class A(object):
"""多态"""
def __init__(self,name):
self.name = name
@staticmethod
def Let_s_go(obj): #统一接口
obj.go()
class B(A):
def go(self):
print("%s去上班"%self.name)
class C(A):
def go(self):
print("%s去玩"%self.name)
b = B("你")
c = C("她")
A.Let_s_go(b)
A.Let_s_go(c)
"""
你去上班
她去玩"""
高级语法部分
静态方法@staticmethod——>只是名义上归类管理,实际上在静态方法里访问不了类或实例中的任何属性
class D(object):
def __init__(self,name):
self.name = name
@staticmethod #为静态方法
def eat(self):
"""为静态方法,把方法和类关系截取掉,变成一个单纯的函数"""
print(self.name)
d = D("子欣")
d.eat(d)
类方法@classmethod----->只能访问类变量,不能访问实例变量
class D(object):
name = "类变量"
def __init__(self,name):
self.name = name
@classmethod #为类方法
def eat(self):
print(self.name)
d = D("子欣")
d.eat()
属性方法@property----->把一个方法变成一个静态属性,属性方法默认不能删除
class D(object):
name = "类变量"
def __init__(self,name):
self.name = name
self.__f = None
@property #方法变成属性
def eat(self):
print(self.name,self.__f)
@eat.setter #给属性赋值
def eat(self,f):
print(f)
self.__f = f
@eat.deleter #删除属性方法
def eat(self):
del self.__f
print("删除属性方法")
d = D("子欣")
d.eat
d.eat = "属性值"
d.eat
del d.eat #再调用会出错
"""
子欣 None
属性值
子欣 属性值
删除属性方法
"""
类的特殊方法
__doc__类的描述信息
class D(object):
"""描述__doc__"""
def __init__(self,name):
self.name = name
self.__f = None
print(D.__doc__) #描述__doc__
__module__表示当前的对象来自那个模块
__class__ 表示当前操作对象的类的信息
from new_dir.sd import SD
obj = SD
print(obj.__module__) #new_dir.sd
print(obj.__class__) #<class 'type'>
__call__ 调用执行的对象D()()
class D(object):
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print("这是call",args,kwargs)
d = D("子欣")
d(1,2,3,name="asd") #这是call (1, 2, 3) {'name': 'asd'}
__dict__查看类或对象中的所有成员
class D(object):
def __init__(self,name):
self.name = name
print(D.__dict__) #打印类里的所有属性,不包括实例属性
d = D("日期")
print(d.__dict__) #打印所有实例属性,不包括类属性 {'name': '日期'}
__str__如果一个类中定义了__str__方法时,打印的对象不再是内存地址,改变默认输出该方法的返回值。
class D(object):
def __init__(self,name):
self.name = name
def __str__(self):
return "<obj:%s>" %self.name
d = D("日期")
print(d) #<obj:日期>
把实例变成字典用索引操作
__getitem__获取
__setitem__设置
__delitem__删除
class Cs(object):
def __init__(self):
self.dict_1 ={}
def __getitem__(self, item):
print('__getitem__:',item)
return self.dict_1.get(item)
def __setitem__(self, key, value):
print('__setitem__:',key,value)
self.dict_1[key] = value
def __delitem__(self, key):
print('__delitem__:',key)
obj = Cs()
obj['name'] = "名字"
print(obj['name'])
del obj['name']
print(obj.dict_1)
"""
__setitem__: name 名字
__getitem__: name
名字
__delitem__: name
{'name': '名字'}
"""
类的起原为type,通过type来写一个类
def func(self):
print("hello%s"%self.name)
def __init__(self,name,age):
self.name =name
self.age = age
D = type("D",(object,),{"func":func, #实例化叫D的类,()括号为他继承谁,"func":func 表示有哪些方法前面命名,后面内存地址
"__init__":__init__})
d = D("类",22)
d.func() #hello类
print(type(D)) #type为类的类 <class 'type'>
创建类的过程
类默认是由type类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性__metaclass__,其用来表示该类由谁来实例化创建,
所以可以__metaclass__设置一个tyPe类的派生类,从而查看类创建的过程:
class MTtype(type):
def __init__(self,what,bases=None,dict=None):
print("MTtype __init__")
super(MTtype,self).__init__(what,bases,dict)
def __call__(self, *args, **kwargs): #__call__用来创建__new__
print("MTtype __call__")
obj = self.__new__(self,*args,**kwargs)
self.__init__(obj,*args,**kwargs)
class F(object):
__metaclass__ = MTtype
def __init__(self,name):
self.name = name
print("F:__init__")
def __new__(cls, *args, **kwargs): #__new__会在__init__前自动执行
print("F:__new__") #是通过__new__来实例化的,__new__用来创建实例的
return object.__new__(cls) #继承父类的__new__方法
f = F("名字")
print(f.name)
反射——> 通过字符串映射或修改程序运行时的状态、属性、方法,有以下4个方法
hasattr(object, name)判断一个对象obj里是否有对应的属性名name、方法,存在返回True getattr(object, name, default) 判断obj中是否有对应的属性名name,有就返回该方法、属性,当没有时,如有传入第三参数就返回第三参数,如没有就报错。 setattr(object, name, value)(对象,属性名,属性值)用于设置属性值,增加属性 或 对存在属性进行修改 delattr(object, name) 判断一个对象obj里是否有对应的属性名name、方法,如果存在就删除命名属性def bulk(self): print("%s想要吃..." % self.name) class D(object): def __init__(self,name): self.name =name def eat(self,food): print("%s 正在吃 %s..."%(self.name,food)) d = D("小红红") input_1 = input(">>:").strip() if hasattr(d,input_1): #判断d类中方法、属性是否存在,存在返回True func = getattr(d,input_1) # 判断d类中方法、属性是否存在,存在返回该方法、属性 func("包子") #eat else: setattr(d,input_1,bulk) func = getattr(d,input_1) func(d) #增加一个属性 func(d) = bulk 属性名,属性值