面向对象

#class 定义一个类,类名一般首字母大写
#def 定义一个函数,自带self形参
# 类中包含两种内容:1、静态属性(变量); 2、动态属性(方法、函数)
class Test:
    s1 = 'test'

    def __init__(self, a):
        self.aa = a
        print('init', self, self.aa) # init <__main__.Test object at 0x7f920ea10f70> aaa 创建对象时会自动执行

    def T1(self, b):
        return b

#类名的用途:1、访问静态和动态属性;2、创建一个对象;
print(Test.s1) # test  直接访问静态属性

print(Test.T1(1, 2))# 2  直接访问动态属性,因为init会默认执行,所以需要给init传值

print(Test.__dict__)# 类的内容以字典形式存储,内置函数dict可查看
"""
{'__module__': '__main__', 's1': 'test', '__init__': <function Test.__init__ at 0x7f805fa06dc0>, 'T1': <function Test.T1 at 0x7f805fa06f70>, '__dict__': <attribute '__dict__' of 'Test' objects>, '__weakref__': <attribute '__weakref__' of 'Test' objects>, '__doc__': None}
"""

obj = Test('aaa')# 创建对象,格式: 对象 = 类名(init所需参数) 
print(obj) # <__main__.Test object at 0x7fdb6498ffa0>
print(obj.aa) # aaa

re = obj.T1('b')
print(re)# b


from math import pi
# 对象嵌套
class Circular():
    def __init__(self, r);
        self.r = r

    def C(self):
        return 2 * pi * self.r

    def S(self):
        return pi * self.r ** 2

class Ring():
    def __init__(self, in_r, out_r):
        self.in_r = Circular(in_r)
        self.out_r = Circular(out_r)

    def C(self):
        return self.out_r.C() - self.in_r.C()

    def S(self):
        return self.out_r.S() - self.in_r.S()

a = Ring(5, 10)
print(a.C())

 

#三大特性:继承、封装、多态
#继承:
    # 1、解决代码的重复性

#单继承
class C1(): # 父类、基类、超类
    def __init__(self, c1):
        self.c1 = c1

class C2(C1): # 子类、派生类 括号里只能传类名
    def __init__(self, c2):
        self.c2 = c2
        super().__init__(5) # 当父、子类均有init(或重名)时,使用父类init需要 super() 加载父类对象

print(C2.__bases__) # (<class '__main__.C1'>,)  查看父类
print(C1.__bases__) # (<class 'object'>,) 没有父类就是object,object是所有类的父类

test = C2(3)
print(test.c2) # 3
print(test.c1) # 5

#多继承
class B1():
    def __init__(self, b1):
        self.b1 = b1

class B2():
    def __init__(self, b2):
        self.b2 = b2

class B3(B1, B2):
    def __init(self, b3):
        self.b3 = b3
        B1.__init__(self, 8)
        B2.__init__(self, 9) # 多继承需要指定父类,且传参要写self

test = B3(7)
print(test.b3) # 7
print(test.b2) # 9

 

#抽象类: 规范所有继承这个类的子类必须实现 @abstractmethod 装饰的方法
    # 在类的位置指定 metaclass=ABCMeta
    # 在指定的方法上加 @abstractmethod 装饰器

# 接口类(Java知识点): 多继承抽象类,两种类都不能被实例化

from abc import abstractmethod, ABCMeta


class P1(metaclass=ABCMeta):
    @abstractmethod
    def p1(self, str): # 父类约束
        pass

class log1(P1):
    def p1(self, str): # 子类继承父类受父类约束,必须实现p1方法
        print(str)
        return str

class log2(P1):
    def l2(self, str):
        pass
    def p1(self, str): # 必须实现p1方法,否则抛异常
        print(str)

def Pr(obj, str):pbj.p1(str)

L1 = log1()
Pr(L1, 'hahaha')
L2 = log2()
Pr(L2, 'L2')

#钻石继承
class A:
    def func(self):
        print('A')

class B(A):
    # B和C类都继承A,当B没有func()对象时,遵循广度优先算法;如果B和C继承不同类,遵循深度优先
    # def func(self):
    #     print('B')
    pass

class C(A):
    def func(self):
        print('c')

class D(B, C):pass

d = D()
d.func() # c

# 类名.mro() 可以直接将继承顺序输出,super()父类继承也遵循该顺序
print(D.mro())# [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
#多态,Java类需指定参数的类型,将多种类型定义到一个类中,后续类继承定义了多种数据类型的类,即为多态;
    #python不需要指定参数类型,默认多态

#封装
class E():
    def __init__(self):
        self.__test = 'T' # 双下划线定义为 私有变量; 注意类的外部不可以定义私有变量
        print('11111', test) # 直接输出会输出对象  11111 <__main__.B3 object at 0x7f85ab209e80>
        self.test1 = 'T1'
        self.__test2()

    def __test2(self): # 私有方法
        print('Test2')

    def test3(self):
        print(self.__test)

class F(E):
    def __init__(self):
        self.__test2()

e = E()
# print(e.__test)# 异常,私有变量在类外部不可用
print(e.__dict__) # 返回字典中有 _E__test 一个变量,其实是私有变量的名字 {'_E__test': 'T', 'test1': 'T1'}
print(e._E__test) # T 可以强制访问到,但不推荐
print(e.test1) # T1

#e.__test2()# 异常,私有类不能在外部使用
e.test3() # T

# f = F()# 异常,私有类不能继承,所以子类也不可用

 

posted @ 2024-08-13 21:01  尐少  阅读(10)  评论(0)    收藏  举报