面向对象

面向对象

面向对象编程:是一类相似功能函数的集合,使你的代码更清晰化,更合理化

1.面向对象的结构(第一部分:静态属性 属性 静态变量 静态字段)/(第二部分:方法 函数 动态属性)

class Stu:
    study = "学习"#静态属性
    exam = "考试"#静态属性

    def work(self):#动态属性
        print("每天上课")
    def homework(self):
        print("写作业")
class是类的关键字,即为定义一个类
Stu为类名  使用大驼峰命名风格 首字母大写

2.类名操作静态属性

1查看类中的内容:.__dict__ 类名.__dict__
class Stu:
    study = "学习"#静态属性
    exam = "考试"#静态属性

    def work(self):#动态属性
        print("每天上课")
    def homework(self):
        print("写作业")
print(Stu.__dict__)
#{'__module__': '__main__', 'study': '学习', 'exam': '考试', 'work': <function Stu.work at 0x000001280185CBF8>, 'homework': <function Stu.homework at 0x000001280185CC80>, '__dict__': <attribute '__dict__' of 'Stu' objects>, '__weakref__': <attribute '__weakref__' of 'Stu' objects>, '__doc__': None}

2.万能的点.
class Stu:
    study = "学习"#静态属性
    exam = "考试"#静态属性

    def work(self):#动态属性
        print("每天上课")
    def homework(self):
        print("写作业")
print(Stu.__dict__)
查
print(Stu.study)
print(Stu.exam)

增
Stu.close = "校服"
print(Stu.close)

删
del Stu.close
print(Stu.__dict__)

改
Stu.exam = "不想考试"
print(Stu.exam)

3.类名操作动态方法

class Hun:
    mind = "有点思想"
    dic = {}
    l1 = []
    def work(self):
        print("人类会工作")
    def too(self):
        print("人类会使用工具")
hun.work(11)#11为参数,work中的self需要接受一个参数

4.从对象的角度研究类

类名+()就是一个实例化过程 就会实例化成一个对象
class Human:
    mind="有思想"
    language = "使用语言"
    def __init__(self,name,sex,age,hobby):
   #self就是类中方法的第一个位置参数,self 和obj指向的同一内存地址 name,sex,age,hobby就是self封装的四个属性
        self.姓名=name
        self.性别 = sex
        self.年龄 = age
        self.爱好 = hobby
        print(self)#<__main__.human object at 0x00000258965EDC18>
        #self 和obj指向的同一内存地址

obj = Human("barry","男",18,"运动")
obj.职业 = "it"#增
obj.性别 = "女"#改
del obj.性别   #删
print(obj.年龄)#查
print(obj.__dict__)
print(obj)#<__main__.Human object at 0x00000258965EDC18>
1.在内存中开辟了一个对象空间
2.自动执行类中的__init__方法,并将这个对象空间(内存地址)传给了__init__方法的第一个位置参数self。
3.在__init__ 方法中通过self给对象空间添加属性

一个类实例化多个对象
class Human:
    mind="有思想"
    language = "使用语言"
    def __init__(self,name,sex,age,hobby):
        self.姓名=name
        self.性别 = sex
        self.年龄 = age
        self.爱好 = hobby
obj1 = Human('小胖','男',20,'美女')
obj2 = Human('相爷','男',22,'肥女')
print(obj1.__dict__)
print(obj2.__dict__)
#{'姓名': '小胖', '性别': '男', '年龄': 20, '爱好': '美女'}
 {'姓名': '相爷', '性别': '男', '年龄': 22, '爱好': '肥女'}

继承

继承的有点也是显而易见的:
1,增加了类的耦合性(耦合性不宜多,宜精)。
2,减少了重复代码。
3,使得代码更加规范化,合理化

# 单继承
class People:
    mind = "有思想的"
    def __init__(self,name,age):
        self.name = name
        self.age = age
class Animal(People):
    mind = "无脑的"

People为父类,基类,超类,Animal为子类,派生类
obj = People("八戒",36)
obj1 = Animal("八戒",36)
实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。
先要执行自己类中的方法,自己类没有才能执行父类中的方法
print(obj.mind)
print(obj1.mind)


# 同时执行类和父类的方法
# 方法一
class Ainmal:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class People:
    def __init__(self,name,age,sex,hobby): #父类方法重构 增加hobby是为了区别人类和动物的区别,但还要用之前人和动物的共同属性,在原来的基础上增加hobby
        Ainmal.__init__(self,name,age,sex) #调用Ainmal中的__init__
        self.hobby = hobby                 #添加hobby
obj = Ainmal("八戒",36,"男")
obj1 = People("八戒",36,"男","女")
print(obj.__dict__)
{'name': '八戒', 'age': 36, 'sex': '男'}
print(obj1.__dict__)
{'name': '八戒', 'age': 36, 'sex': '男', 'hobby': '女'}


# 方法二
class Ainmal:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

class People(Ainmal):
    def __init__(self,name,age,sex,hobby):
        super(People,self).__init__(name,age,sex) # 完整版
        super().__init__(name,age,sex)            # 简写版
        self.hobby = hobby

obj = People("八戒",36,"男","女")
print(obj.__dict__)
{'name': '八戒', 'age': 36, 'sex': '男', 'hobby': '女'}


class Ainmal:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        print("吃饭")
class People(Ainmal):
    def __init__(self, name, age, sex, hobby):
        super(People, self).__init__(name, age, sex)  # 完整版
        super().__init__(name, age, sex)  # 简写版
        self.hobby = hobby

    def eat(self):
        super().eat()   #调用父类中的方法
        print(f"{self.name}吃饭")
obj = People("八戒", 36, "男", "女")
print(obj.__dict__)
obj.eat()
# 吃饭
# 八戒吃饭


# 单继承练习
# 第一题
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)

class Foo(Base):
    pass
obj = Foo(123)
obj.func1()
"""
先在本类中找 Foo为本类
1.obj = Foo(123)实例化对象,自动执行__init__方法,此时self = obj,num = 123
2.执行obj.func1(),首先在Foo的类中找func1,Foo中没有,到父类中找func1,执行func1 ,打印123
"""

# 第二题
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
class Foo(Base):
    def func1(self):
        print("Foo. func1", self.num)
obj = Foo(123)
obj.func1()
"""
先在本类中找 Foo为本类
1.obj = Foo(123)实例化对象,自动执行__init__方法,此时self = obj,num = 123
2.执行obj.func1(),首先在Foo的类中找func1,Foo有,则执行func1 ,打印   Foo. func1 123
"""

# 第三题
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print("Base.func2")
class Foo(Base):
    def func2(self):
        print("Foo.func2")
obj = Foo(123)
obj.func1()
"""
先在本类中找 Foo为本类
1.obj = Foo(123)实例化对象,自动执行__init__方法,此时self = obj,num = 123
2.执行obj.func1(),首先在Foo的类中找func1,Foo中没有,去父类中找func1,父类中有,则执行func1 ,打印123
3.继续执行func2 也是先去Foo中找func2 找到则执行,找不到则在父类中继续找 结果 123  Foo.func2
"""

# 第四题
class Base:
    def __init__(self, num):
        self.num = num
    def func1(self):
        print(self.num)
        self.func2()
    def func2(self):
        print(111, self.num)
class Foo(Base):
    def func2(self):
        print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
    obj.func2()
"""
1.Base(1), Base(2), Foo(3)实例化,num分别为1,2,3
2.循环列表 1.Base(1)在执行Base(1)中的func2中内容 打印111 1  2.Base(2)中的func2中内容 打印111 2  3.执行Foo(3)在Foo中内容 222 3
"""

多继承

在python2x版本中存在两种类.:
  ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写.
  ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。
python3x版本中只有一种类:
python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
class E:
    pass
class F(D, E):
    pass
class G(F, D):
    pass
class H:
    pass
class Foo(H, G):
    pass
MRO: Foo-> H -> G -> F -> E -> D -> B -> A -> C(看图)
    
print(Foo.mro())******(直接计算)

原则:从头开始. 从左往右. ⼀条路跑到头, 然后回头. 继续⼀条路跑到头. 就是经典类的MRO算法. 

1565095855639

封装 和 多态

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

所以,在使用面向对象的封装特性时,需要:

  • 将内容封装到某处
  • 从某处调用被封装的内容封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
封装
class foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age
obj1 = foo("wupeiqi",18)
obj2 = foo("alex",73)
通过对象直接调用被封装里的内容
print(obj1.name)
print(obj1.age)
print(obj2.name)
print(obj2.age)

class foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def info(self):
        print(self.name)
        print(self.age)
间接通过self调用
obj1 = foo("wupeiqi",18)
obj2 = foo("alex",73)
obj1.info()
obj2.info()


多态

多态,同一个对象,多种形态。python默认支持多态。
ython中有一句谚语说的好,你看起来像鸭子,那么你就是鸭子。
对于代码上的解释其实很简答:
class A:
    def f1(self):
        print('in A f1')
    
    def f2(self):
        print('in A f2')

class B:
    def f1(self):
        print('in A f1')
    
    def f2(self):
        print('in A f2')
       
obj = A()
obj.f1()
obj.f2()

obj2 = B()
obj2.f1()
obj2.f2()
# A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
# 对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。

# 这样的例子比比皆是:str  tuple list 都有 index方法,这就是统一了规范。
# str bytes 等等 这就是互称为鸭子类型。

类的约束

提取⽗类. 然后在⽗类中定义好⽅法. 在这个⽅法中什么都不⽤⼲. 就抛⼀个异常就可以了.
这样所有的⼦类都必须重写这个⽅法. 否则. 访问的时候就会报错.
方法1*****
class payment:
    def pay(self,money):
        raise Exception("子类没有引用pay方法")
        #手动添加报错信息
class qqpay(payment):
    def pay(self,money):
        print(f"使用QQ支付{money}")

class wechatpay(payment):
    def pay(self,money):
        print(f"使用QQ支付{money}")

class Alipaypay(payment):
    def zhifu(self,money):
        print(f"使用支付支付{money}")

def pay(obj,money):统一接口(支付接口,方便其他文件的互相调用)
    obj.pay(money)

obj1 = qqpay()
obj2 =wechatpay()
obj3 =Alipaypay()

pay(obj1,100)
pay(obj2,100)
pay(obj3,100)


方法2:抽象类,接口类 :强制指定规则
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self,money):
        pass
class qqpay(Payment):
    def pay(self,money):
        print(f"使用QQ支付{money}")

class wechatpay(Payment):
    def pay(self,money):
        print(f"使用QQ支付{money}")

class (Payment):
    def pay(self,money):
        print(f"使用支付宝支付{money}")
def pay(obj,money):
    obj.pay(money)

obj1 = qqpay()
obj2 =wechatpay()
obj3 =Alipaypay()

pay(obj1,100)
pay(obj2,100)
pay(obj3,100)

super深度深入了解

class A:
    def f1(self):
        print('in A')

class Foo(A):
    def f1(self):
        super().f1()
        print('in Foo')

class Bar(A):
    def f1(self):
        print('in Bar')

class Info(Foo,Bar):
    def f1(self):
        super().f1()
        print('in Info f1')
 print(Info.mro())#  Info--》Foo--》Bar--》A--》object

obj = Info()
obj.f1()
1.实例化一个对象
2.先在info的类中找f1 info中有f1 执行super().f1 去Foo中找f1,打印'in Foo' 在打印 'in Info f1' 按照mro算法的执行顺序向父类中查找

class A:
    def f1(self):
        print('in A')

class Foo(A):
    def f1(self):
        super().f1()
        print('in Foo')

class Bar(A):
    def f1(self):
        print('in Bar')

class Info(Foo,Bar):
    def f1(self):
        super(Foo,self).f1()
        print('in Info f1')

obj = Info()
obj.f1()
1.实例化一个对象
2.先在Info 中找f1 ,执行 super(Foo,self).f1() 到Foo中找f1 在执行Foo中的super().f1() 在到Bar中找f1 打印in Foo 在打印in Info f1 按照mro算法的执行顺序向父类中查找
Info--》Foo--》Bar--》A--》object
3.严格按照对象从属于类的mro的顺序,查询下一个类.

类的成员

  1. 细分类的成员
class C:
    name = '公有静态字段/变量'
    _phone = 15032551128    #私有静态变量
    def __init__(self,name):#特殊方法
        self.name = name

    def func(self):          #普通方法
        print(C.name)

    def _func(self,name):    #私有方法
        self.name = name
        print('私有方法')
class d(C):
    def show(self):
        print(C.name)

    @classmethod
    def class_func(cls):
        print("类方法")

    @staticmethod
    def static_func():
        print("静态方法")

    @property
    def prop(self):
        print("属性")
obj = C("八戒")
print(obj.name)
print(C.nunc()
obj1 = d(1)
obj1.show()


  1. 类的私有成员
公有成员,在任何地方都能访问
私有成员,只有在类的内部才能方法
静态字段(静态属性)	
   公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
class C:

    name = "公有静态字段"

    def func(self):
        print (C.__name)

class D(C):

    def show(self):
        print (C.__name)


C.name         # 类访问
obj = C()
obj.func()     # 类内部可以访问
obj_son = D()
obj_son.show() # 派生类中可以访问    


   私有静态字段:仅类内部可以访问;
class C:

    __name = "私有静态字段"

    def func(self):
        print (C.__name)

class D(C):

    def show(self):
        print (C.__name)


C.__name       # 不可在外部访问
obj = C()
obj.__name     # 不可在外部访问
obj.func()     # 类内部可以访问  
obj_son = D()
obj_son.show() #不可在派生类中可以访问 

***************************************************
普通字段(对象属性)

1.公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
class C:
    
    def __init__(self):
        self.foo = "公有字段"

    def func(self):
        print(self.foo)  # 类内部访问

class D(C):
    
    def show(self):
        print(self.foo) # 派生类中访问

obj = C()
obj.foo     # 通过对象访问
obj.func()  # 类内部访问
obj_son = D();
obj_son.show()  # 派生类中访问


2.私有普通字段:仅类内部可以访问
class C:  
    def __init__(self):
        self.__foo = "私有字段"

    def func(self):
        print(self.foo)  # 类内部访问

class D(C):
    def show(self):
        print(self.foo) # 派生类中访问

obj = C()
obj.__foo     # 通过对象访问    ==> 错误
obj.func()  # 类内部访问        ==> 正确
obj_son = D()
obj_son.show()  # 派生类中访问  ==> 错误



*****************************************************************************************************
 类的私有成员
1.在类的内部访问
class A:
    name = "liye"
    __name = "gangge"
    def func(self):
        print(self.name)    #类的内部
        print(self.__name)  #类的内部
obj = A()
obj.func()

类的外部不能访问私有方法
class A:
    name = "liye"
    __name = "gangge"
    def func(self):
        pass
obj = A()
print(obj.name)    #liye
print(A.__name)    #错误
print(obj.__name)  #错误

类的派生类不能访问
class A:
    name = '李业'
    __name = '钢哥'

class B(A):
    def func(self):
        print(self.__name)

obj = B()
# print(obj.__name)
obj.func()


总结:私有对象属性只能在类的内部使用,不能再类外部以及派生类使用.

class A:
    def __init__(self,name,pwd):
        self.name = name
        self.pwd = pwd
    def md5(self):
        self.__pwd = self.__pwd + "123"
obj = A("八戒",123456)
print(obj.__pwd) #'A' object has no attribute '__pwd' 错误
私有成员来说: 当你遇到重要的数据,功能,(只允许本类使用的一些方法,数据)设置成私有成员.
python所有的私有成员都是纸老虎,形同虚设.

class A:

    name = '李业'
    __name = '钢哥'  # 私有类的属性

    def __func(self):
        print('in __func')

print(A.__dict__)
print(A._A__name)#别用

类从加载时,只要遇到类中的私有成员,都会在私有成员前面加上_类名 .


类的其他方法

类方法有什么用???
    1. 得到类名可以实例化对象.
    2. 可以操作类的属性.
class A:
    def func(self):
        print('实例方法')
    @classmethod    #类方法
    def cls_func(cls):
        print(f'cls---->{cls}')#<class '__main__.A'>
        obj = cls()
        print(obj)
        print('类方法')
print(A) #<class '__main__.A'>
A.cls_func()
obj = A()
obj.cls_func()
类方法: 一般就是通过类名去调用的方法,并且自动将类名地址传给cls,
但是如果通过对象调用也可以,但是传的地址还是类名地址


创建学生类,只要实例化一个对象,写一个类方法,统计一下具体实例化多少个学生?
原则上,类方法是将类本身作为对象进行操作的方法,默认有个 cls 参数,可以被类和对象调用
通过实例化一个对象就执行一次 __init__方法 然后调用add 函数 执行自动加1
class Student:

    count = 0
    def __init__(self,name,id):
        self.name = name
        self.id = id
        Student.add()

    @classmethod
    def add(cls):
        print(cls)
        cls.count+=1

    @classmethod
    def get(cls):
        return cls.count

obj1 =Student("liye",2542621222)
obj1 =Student("liye",2542621222)
obj1 =Student("liye",2542621222)
print(obj1)
print(Student.get())

class student:
    count = 0
    def __init__(self,name,id):
        self.name = name
        self.id = id
        student.add()

    @classmethod
    def add(cls):
        cls.count += 1

        return cls.count
obj = student("d",252531)
obj1 = student("d",252531)
obj2 = student("d",252531)
print(student.count)
student.add()


静态方法
class A:

    def func(self):
        print('实例方法')


    @classmethod
    def cls_func(cls):
        pass

    @staticmethod
    def static_func():
        print('静态方法')

静态方法是不依赖于对象与类的,其实静态方法就是函数.
保证代码的规范性,合理的划分.后续维护性高.

@property的组合
class Foo:

    @property
    def bmi(self):
        print("1")
    @bmi.setter
    def bmi(self,v):
        print(2)
    @bmi.deleter
    def bmi(self):
        print(3)

obj = Foo()
obj.bmi       #不加括号也可以直接调用bmi 函数
obj.bmi = 666 #操作命令,这个命令并不是改变bmi的值,而知执行被bmi.setter装饰器装饰的函数 得不到返回值(return)
del obj.bmi   #操作命令,这个命令并不是删除bmi的值,而知执行被bmi.setter装饰器装饰的函数 得不到返回值(return)


 利用实例化对象的方式设置属性.

class Foo:
    def get_AAA(self):
        print('get的时候运行我啊')

    def set_AAA(self,value):
        print('set的时候运行我啊')

    def delete_AAA(self):
        print('delete的时候运行我啊')

    AAA = property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应

f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
*****************************************************************************************************


isinstance(a,b):判断a是否是b类(或者b类的派生类)实例化的对象
issubclass(a,b): 判断a类是否是b类(或者b的派生类)的派生类
posted @ 2019-08-12 19:03  corei5tj  阅读(200)  评论(0编辑  收藏  举报