面向对象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的保留方法,称为魔幻方法"""

浙公网安备 33010602011771号