1 python对于代码对齐有严格的要求,不对齐会报错
关于self和clk
1 self代表实例对象,cls代表类
2 类中的变量self是每一个实例对象本身
class A:
def get_self(self):
return self
#self 是类的每一个实例对象本身!比如下面的self就是a1
a1 = A()
print(a1.get_self()) # <__main__.A object at 0x00000250D18C66C8>
a2 = a1.get_self()
print(a1 is a2) # True 说明 a1 和 a2 是同一个实例对象
#下面的self就是a3
a3 = A()
print(a3 is a1) # False 说明 a3 是一个新的实例对象
a4 = a3.get_self()
print(a4 is a3)
运行结果
3
class A:
class_public = "class public" # 类的公有变量
_class_protected = "class protected" # 类的保护变量 类对象和子类对象能访问
__class_private = "class private" # 类的私有变量 只允许类本身访问,子类也不行
name = "class A"
def __init__(self):
name = 'Local A' # 局部变量
self.name = "self A"
self.instance_public = "instance public" # 实例的公有变量
self._instance_protected = "instance protected" # 实例的保护变量
self.__instance_private = "instance private" # 实例的私有变量
print(name) # Local A 优先访问局部变量
a = A()
# 实例的私有变量,每个类的实例拥有自己的私有变量,各个实例的私有变量互不影响。
print(a.name) # self A 同名的 实例私有变量 覆盖了 类的公有变量
print(a.class_public) # class public
print(a._class_protected) # class protected (Pycharm 提示: Access to a protected member _instance_protected of a class)
#类的私有变量 类的实例也不可以访问
# print(a.__class_private) # AttributeError: 'A' object has no attribute '__class_private'
print(a.instance_public) # instance public
print(a._instance_protected) # instance protected (Pycharm 提示: Access to a protected member _instance_protected of a class)
#实例也不可以访问实例的私有变量?
# 大概是因为 这样访问是在类外访问 是不可以的
# print(a.__instance_private) # AttributeError: 'A' object has no attribute '__instance_private'
# 类内,函数外定义的变量,都是类的变量,所有类内函数需要通过 cls 关键字访问类的变量,外部可直接 类名.公有变量名 访问类的公有变量
print(A.name) # class A
print(A.class_public) # class public
print(A._class_protected) # class protected (Pycharm 提示: Access to a protected member _class_protected of a class)
#类外不可以访问类内的私有变量?
# print(A.__class_private) # AttributeError: type object 'A' has no attribute '__class_private'
A.name = "Changed class A" # 修改公有变量
print(A.name)
A._class_protected = "Changed class protected" # 修改保护变量
print(A._class_protected)
运行结果
解决方法:Python中访问类中的私有变量的两种方法_类的私有变量怎么访问-CSDN博客
class Person(object):
def __init__(self):
self.__age = 18 # 定义一个私有化属性,属性名字前加连个 __ 下滑线
def get_age(self): # 访问私有实例属性
return self.__age
def set_age(self,age): # 修改私有实例属性
if age < 0:
print('年龄不能小于0')
else:
self.__age = age
age = property(get_age,set_age) # 定义一个属性,当对这个age设置值时调用set_age,
# 当获取值时调用get_age
# 注意:必须是以get,set开头的方法名,才能被调用
xiaoming = Person()
print(xiaoming.age)
xiaoming.age = 15
print(xiaoming.age)
运行结果
3 以通过 cls.变量名
访问,不过只能在类方法 @classmethod
内访问
class Fruit(object):
total = 0
@classmethod
def print_total(cls):
print(cls.total)
# print(id(Fruit.total))
# print(id(cls.total))
@classmethod
def set_total(cls, value):
print(f"调用类方法 {cls} {value}")
cls.total = value
class Apple(Fruit): pass # 继承Fruit类
class Banana(Fruit): pass # 继承Fruit类
Fruit.print_total() # 0 注意:此处是0,我们会发现后面Apple、Banana修改total不会影响此值
a1 = Apple()
a1.set_total(200) # 调用类方法 <class '__main__.Apple'> 200
a2 = Apple()
a2.set_total(300) # 调用类方法 <class '__main__.Apple'> 300
a1.print_total() # 300
a2.print_total() # 300
Apple.print_total() # 300
b1 = Banana()
b1.set_total(400) # 调用类方法 <class '__main__.Banana'> 400
b2 = Banana()
b1.print_total() # 400
b2.print_total() # 400
Banana.print_total() # 400
Fruit.print_total() # 0
Fruit.set_total(100) # 调用类方法 <class '__main__.Fruit'> 100
Fruit.print_total() # 100
# 不管创建多少个 Apple 或 Banana 的实例对象,这些实例对象都是共用一个 cls.total
# 通过类方法 @classmethod 关键字定义的函数可以修改类的公有变量。
# 调用@classmethod方法的时候隐形传入的参数为该对象所对应的类
运行结果
定制类和魔法方法
在 Python 中,我们可以经常看到以双下划线 __
包裹起来的方法,比如最常见的 __init__
,这些方法被称为魔法方法(magic method)或特殊方法(special method)。简单地说,这些方法可以给 Python 的类提供特殊功能,方便我们定制一个类,比如 __init__
方法可以对实例属性进行初始化。
【我理解的,第一个实例之后,类定义的最后一句才执行,所以定义第一个实例的时候,key还不在A._dict中,所以第一个实例输出的是NEW;大概这样吧,鬼东西乱七八糟的,烦的嘞】
下面这个是讲str函数的
slot魔法
在 Python 中,我们在定义类的时候可以定义属性和方法。当我们创建了一个类的实例后,我们还可以给该实例绑定任意新的属性和方法
这种动态绑定的功能虽然很有用,但它的代价是消耗了更多的内存,因此,为了不浪费内存,可以使用 __slots__
来告诉 Python 只给一个固定集合的属性分配空间,对上面的代码做一点改进,如下:
使用 __slots__
有一点需要注意的是,__slots__
设置的属性仅对当前类有效,对继承的子类不起效,除非子类也定义了 __slots__
,这样,子类允许定义的属性就是自身的 slots 加上父类的 slots
关于@property的使用
原文:使用 @property · explore-python
关于super
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用 super
来实现
涉及super的多重继承
代码如下:
运行结果
enter A 的下一句不是 enter Base 而是 enter B,是因为,super
和父类没有实质性的关联,现下面介绍 super
是怎么运作的。
那么对于代码中的例子,语句
super(C, self).__init__()
这里的 self 是当前 C 的实例,self.class.mro() 结果是:【遵循上面图中画红框部分的原则】
[__main__.C, __main__.A, __main__.B, __main__.Base, object]
元类metaclass
① 类也是对象
② type
经常使用它来判断一个对象的类型如下图,事实上,type
除了可以返回对象的类型,它还可以被用来动态地创建类(对象)
有属性和方法的情况:不知道最后为什么会输出一个NONE?
③ 什么是元类(metaclass)
陌生的 metaclass · explore-python