新的一年到了,回顾一下2022年。虽然考研考上了,但却摸鱼摸了大半年,每周一次的组会都心惊胆战。随着这篇博客的发布,希望给自己立点flag,还是认真对待点,毕竟选择的人工智能方向也是自己喜欢的方向。接下来将持续更新python的基础语法,一直到pytorch和深度学习模型的代码等等,方便自己复习、记录遇到的坑。
简单来说,就是设置一些“私有”的属性方法,来有选择的让外界进行交互。
class student:
mark = None
__secret = True
def __init__(self,name,age):
self.name = name
self.__age = age
s = student("李白",18)
print(s.age) #AttributeError: 'student' object has no attribute 'age'
print(s._student__age) #18,可以通过 对象._类名__私有属性的方法强行访问,语法支持但不建议
print(s.__dict__) #可以查看对象s的属性,{'name': '李白', '_student__age': 18}
print(student.__dict__) #可以查看类的属性,有 '_student__secret': True
'''
{
'__module__': '__main__',
'mark': None,
'_student__secret': True,
'__init__': ,
'__dict__': ,
'__weakref__': ,
'__doc__': None
}
'''
值得注意的是,像__module__、__init__等是内置的魔术方法,具体可以查看官方文档:
python官方文档
一般来说,通常会使用私有属性+公有方法的形式来实现有选择的访问:
class student:
mark = None
def __init__(self,name,age):
self.name = name
self.__age = age
def getAge(self):
return self.__age
#还可以加入条件判断等更复杂的代码逻辑
def setAge(self,age):
if 0 < age < 125:
#self.age = age #错
self.__age = age
else:
print("不能随意修改年龄")
s = student("李白",18)
print(s.getAge()) #18
s.setAge(40)
print(s.getAge()) #40
但是,如果对应每个私有属性都要写一套get和set方法,会显得代码非常复杂冗余。对于python来说,提供了装饰器来解决这个问题:
class student:
mark = None
def __init__(self,name,age):
self.name = name
self.__age = age
@property #装饰器,最好把函数名改一下
def age(self):
return self.__age
@age.setter #对应上面装饰器的名字,使其配套
def age(self,age):
if 0 < age < 125:
#self.age = age #错
self.__age = age
else:
print("不能随意修改年龄")
s = student("李白",18)
print(s.age) #可以直接对象.属性的方式,像普通的属性一样
s.age = 40 #也可以直接赋值,跟普通的对象属性赋值没有区别,但实际上是get和set方法
print(s.age) #40
装饰器的使用,只需要在定义函数前加上 @property 就可以实现。
在相似类中可能会定义很多重复的代码,为了简洁。不使用继承:
class Pet:
master = True
def __init__(self,name):
self.name = name
print(f"一个名叫{self.name}的宠物出生了")
def eat(self):
print(f"{self.name}在吃东西")
def sleep(self):
print(f"{self.name}在睡觉")
class Dog:
master = True
def __init__(self,name):
self.name = name
print(f"一个名叫{self.name}的宠物出生了")
def eat(self):
print(f"{self.name}在吃东西")
def sleep(self):
print(f"{self.name}在睡觉")
class Cat:...
class ...
#虽然ctrlc ,ctrlv很简单也很方便,但是在代码中还是尽量少重复
使用继承:
class Pet:
master = True
def __init__(self,name):
self.name = name
print(f"一个名叫{self.name}的宠物出生了")
def eat(self):
print(f"{self.name}在吃东西")
def sleep(self):
print(f"{self.name}在睡觉")
class Dog(Pet):
def __init__(self,name,age,sex):
#super(Dog,self).__init__(name) #两种写法都可以
super().__init__(name)
self.age = age
self.sex = sex
def eat(self):
super(Dog, self).eat() #调用父类方法,并在此基础上进行扩展
print("扩展...")
class Cat(Pet):
pass
d = Dog("haha",18,1)
#d.eat() #haha在吃东西,没有进行任何修改时默认调父类的eat方法
d.eat() # 扩展...
相关概念:
被继承的叫基类,父类,超类
继承的叫子类,子类会默认有父类中公有的方法和属性,私有的不能继承
如果子类中有相应的属性或方法,就用子类的;没有就用父类的。
当子类和父类有同样的属性或方法名时,是子类对父类的扩展或补充,可以使用super(类名,self)来达到调用父类对象的效果 。
class Animal:
def eating(self):
print("吃东西")
class Dog(Animal):
def eating(self):
print("狗在吃东西")
class Cat(Animal):
def eating(self):
print("猫在吃东西")
class Zoo:
def eatingShow(self,animal):
animal.eating()
def __call__(self,animal):
#可以直接对象加()的形式,默认调用该方法
print("调用了__call__方法")
self.eatingShow(animal)
d = Dog()
c = Cat()
z = Zoo()
z(d)
z(c)
# print(isinstance(d,Animal)) #isinstance(A,B),判断一个对象A是否是对象B的子类,可以一直往上。
# print(type(c) is Animal) #False,type只能判断直接类型
补充:
class Dog():
def __init__(self,name):
self.name = name
def __str__(self):
return self.name
d = Dog("haha")
print(d.__dir__())
'''
['name', '__module__', '__init__', '__str__', '__dict__',
'__weakref__', '__doc__', '__repr__', '__hash__',
'__getattribute__', '__setattr__', '__delattr__', '__lt__',
'__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__',
'__reduce_ex__', '__reduce__', '__subclasshook__',
'__init_subclass__', '__format__', '__sizeof__', '__dir__',
'__class__']
'''
print(d) #haha
print(Dog) #