面向对象OOP

补充:

class A:
    def __init__(self, a):
        print(self, a)
        # 注意观察打印结果中self的指向,A被子类继承以后,self指向的不是A,而是子类


class B(A):
    # 这里没有重写父类的__init__方法,会自动调用父类的构造方法, 并且还会自动传递参数a给父类的构造函数
    pass

class C(A):
    def __init__(self, a):
        # 父类的构造方法一旦重写,就不会自动调用父类的构造方法,就不能够正确初始化对象,除非手动调用父类构造方法,如下:
        pass

class D(A):
    def __init__(self, a):
        # 手动调用父类的构造方法,
        super().__init__(a)
        # 或者
        A.__init__(self, a)

A(1111)  # <__main__.A object at 0x0000022E406C7610> 111
B(1111)  # <__main__.B object at 0x0000022E406C7610> 111
C(1111)  # 没有任何输出,说明父类的构造函数并没有调用,
D(1111)  # <__main__.D object at 0x000001A7E65D7BE0> 1111
         # <__main__.D object at 0x00000231C79F7BE0> 1111

 

 

一、

class Parent:  # 定义父类
    def myMethod(self):
        print('调用父类方法')


class Child(Parent):  # 定义子类
    def myMethod(self):
        print('调用子类方法')

    def __del__(self):  # 对象释放时会调用该方法:del c
        print('del')


c = Child()  # 子类实例
c.myMethod()  # 调用子类方法
Child.myMethod(c)  # 调用子类方法
Parent.myMethod(c)  # 调用父类方法
super(Child, c).myMethod()  # 调用父类方法
# super().myMethod()  # 调用父类方法。这种格式只能在类内部使用

# 用类名.对象方法名(对象) 这种格式调用对象方法有什么现实意义:
# 答,比如对象方法作为key参数使用时:以lower()方法为例
# lower()是对象方法:'ABC'.lower()
# 但是我为可以用类来调用:str.lower('ABC'):下面是具体使用方法:


spam = ['a', 'z', 'A', 'Z']
# spam.sort(key=str.lower)
# print(spam)  # ['a', 'A', 'z', 'Z']
# # 说明:str.lower()是一个对象方法,这里用类来调用一个对象方法,需要传递一个对象参数,sort会自动帮你传递这个对象参数


del c

 

 二、

# coding=utf-8
# 代码文件: com/tangjun/test.py

class PremClass():
    # 这是父类 大写字母开头,采用大驼峰命名。
    # 实例方法 需要跟self绑定
    def eat(self):
        print("这是父类的方法")


class MyClass(PremClass):
    # 参数是PremClass,表示要继承的类
    # 这是类变量? 答,是的,只能用类名.变量名访问,这是规定,虽然可以用对象名.变量名访问,但这不符合规范,容易造成混乱
    aaa = 123
    ccc = 1

    # 构造方法
    def __init__(self):
        # super().__init__() # 调用父类构造方法,py不会隐式调用父类构造函数,如果不手动调用,父类将无法初始化变量,除非不要重写父类的构造方法,python就会自动调用父类的构造方法
        # 这是实例变量,外面不可以用MyClass.aaa访问,但是可以用mc.bbb访问
        self.bbb = 345
# 注意,这里的aaa(实例变量)不是外面的aaa(类变量),所以不建议同名 self.aaa = 555
# 下面是私有变量,外面无法方法:用双下(__)划线开头命名 self.__name = "tangent" # 下面的ddd是局部变量。 ddd = 1023 # 重写父类的方法 def eat(self): # super(MyClass, self).eat() # 错误的写法
     # super().eat() # 这是正确的写法
print(self.__name) self.__think() # 类内部可以访问私有方法 print("这是子类的方法") # 私用实例方法,外界无法访问,用双下划线(__)开头命名 def __think(self): pass # 类方法 ,不需要跟self绑定,需要跟类绑定,参数为cls, @classmethod def run(cls): # print(self.bbb) # 无法访问 print(cls.aaa, "----") # 静态方法 @staticmethod def count(): """类方法与静态方法在很多场景是类似的,只 是在定义时有一些区别。 类方法需要绑定类, 静态方法不需要绑定类, 静态方法与类的相合度更加松散。 在一个类中定义静态方法只是为了 提供一个基于类名的命名空间""" print(MyClass.aaa, "===========") pass # 属性 # 因为属必可以只读,所以,下面的setter可以省略,getter和setter的顺序不能颠倒 @property def weight(self): return self.__weight @weight.setter def weight(self, w): self.__weight = m # 重写父类的描述方法,print(myclass) 其实就是调用__str__()方法。默认返回对象的类名, 以及内存地址等信息, def __str__(self): return "MyClass aaa:{0],bbb:{1}".format(self.aaa, self.bbb) # 重写父类的比较方法。 if myclass1 == myclass2: 其实就是调用对象的此方法,默认返回Flase def __eq__(self, other): if self.aaa == other.aaa and self.bbb == other.bbb: return True else: return False m = MyClass() print(m.bbb) # print(m.__name) # 无法访问私有属性 # 注意,aaa是MyCLass的类变量。 print(MyClass.aaa) m.eat() # 类型检查 print(isinstance(m, PremClass)) # True print(isinstance(m, MyClass)) # True # 下面的神操作可以,但是不推荐,这会破坏面向对象的封装性。 # m.name = "tangjun" # print(m.name) # MyClass.count = 11111 # print(MyClass.count) # 查看有哪些实例变量 print(m.__dict__) # {'bbb': 345, 'aaa': 555, 'name': 'tangjun'} # 查看有哪些类变量 print(MyClass.__dict__) """前后都有 __变量__ 双下划线的方法是Python的保留方法,称为魔幻方法"""

 

posted @ 2020-10-07 15:30  老谭爱blog  阅读(125)  评论(0)    收藏  举报