今天算是吧python的class学习完了,之前,pytorch的那篇学习笔记中的问题,再学习后自己思考了一下,得到了答案,之前的疑问,我也会在之前的博客中解答,好的废话不多说,讲讲今天的学习理解,
class Person():
def __init__(self,name):
self.__name=name
print(self.__name)
def get_name(self):
return self.__name
def setter_name(self,name):
self.__name=name
p=Person("孙悟空")
print(p._Person__name)
运行结果
孙悟空
孙悟空
当时看到这里觉得python十分的有意思,它的封装就是自欺欺人的一种方式,在自定义属性的时候使用self__XXX,的样式的时候,python会自动将你的属性改名,在你实例化对象的时候,它会变成实例化对象._类名__属性的形式,这也是这段代码想说明的事情,我在__init__方法下面打印了定义的属性,同时打印了p._Person__name,运行结果是一样的。
class Person():
def __init__(self,name):
self.__name=name
print(self.__name)
@property
def get_name(self):
return self.__name
p=Person("孙悟空")
print(p.get_name)
运行结果
孙悟空
关于python的类的装饰器,我觉得我只是看了这个@property,感觉自己这部分只要知道别人写的代码这是装饰器就好了,至于这个@property,将它挂在类中的方法上,就可以在引用的时候省略一个括号了,例如我这个地方的代码,正常来说,也就是没有写这个装饰器,print(p.get_name)这个代码应该是要写成print(p.get_name())才对的,但是正是因为有了装饰器的存在使得代码的编写时,省略了一个括号
class Animal:
def run(self):
print("会跑~~~~")
def sleep(self):
print("会睡觉~~~")
class Dog(Animal):
def bark(self):
print("会叫~~~")
dog=Dog()
dog.run()
运行结果
会跑~~~~
这段代码说明了子类在继承父类之后会继承父类的所有方法和属性,这里的Dog类中是没有写run方法的,但是我却可以调用出来,这足以佐证我上面说的话
#第一段代码
class A():
def test(self):
print("aaa")
class B(A):
def test(self):
print("bbb")
class C(B):
def test(self):
print("ccc")
c = C()
c.test()
#第二段代码
class A():
def test(self):
print("aaa")
class B(A):
def test(self):
print("bbb")
class C(B):
pass
c = C()
c.test()
运行结果
ccc
bbb
这段代码我想说的事情是,继承之后,python在调用方法的时候是就近原则的,上面的第一个代码在三个class中都有test方法,但是实例化对象调用的时候是调用了classC()中的方法,而第二个代码,在实例化对象中调用classC()中是没有任何的方法所以调用了classB()中的方法
class Animal():
def __init__(self,age):
self.age=age
def get_age(self):
return self.age
class Dog(Animal):
def ages(self):
return super().get_age()
dog=Dog(18)
print(dog.ages())
运行结果
18
关于super,这个地方在我今天下午在使用的时候想了很久,所以这个地方我想多说一点,super这个方法十分的特殊,他和我上一篇文章说到的self有异曲同工之处,self指的就是实例化对象本身,但是super指的却是这个类的父类,我这个地方在Dog中的ages方法中返回了super().get_age(),这实际上就是等于Animal(self).get_age(),super()就等于Animal(self),就是它的父类
class Animal():
def __init__(self,age):
self.age=age
def get_age(self):
return self.age
class Dog(Animal):
def ages(self):
super().get_age()
dog=Dog(18)
print(dog.ages())
今天下午自己在测试这段代码中测试super的用法,发现一直返回为空,后面自己在控制台的,ipython中测试发现有age这个值,而且就是18,实际上是python在执行类的时候会先跑父类,我的父类是有这个值的,也传递到了class Dog() 这个子类的,但是ages方法我没有使用return,没有返回值,所以一直是输出none
class A():
def __init__(self,a):
self.a=a
@staticmethod
def test():
print("方法执行了")
a1=A(1)
a1.test()
运行结果
方法执行了
这里再方法上加上@staticmethod是表示这个方法是静态方法,这使得这个方法和这个类没什么太大的关系,甚至都不需要再函数中设置参数,但是这个方法可以通过实例化的对象调用出来使用
class Person():
def __init__(self,name,age):
self.name=name
self.age=age
p1=Person("孙悟空",18)
print(p1)
运行结果
<__main__.Person object at 0x0000022320684588>
这里我之所以写这个代码是想说明方法的重写,方法的重写我也只写一个方法的重写,其他的大差不差,这里我打印了实例化的对象发现它返回了一个奇怪的东西实际上这个东西是__str__()的返回值,下面的代码会演示__str__()
class Person():
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return "hellow"
p1=Person("孙悟空",18)
print(p1)
运行结果
hellow
我们改写了__str__()这个方法,像这种下划线方法是魔术方法,它会自动运行不用调用,所以,我们一打印实例化的对象就会调用__str__()这个方法,本来程序是会像之前一样返回<__main__.Person object at 0x0000022320684588>,但是因为我们在类中重写了这个方法将程序自带的方法覆盖掉了,所以输出为hellow
class Person():
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return f"{self.name},{self.age}"
p1=Person("孙悟空",18)
print(p1)
输出结果
孙悟空,是18岁
这样做的好处在这里也体现出来了,但是这个__str__()方法一定要返回字符串类型才行