Python面向对象的进阶语法

1.类神奇的魔法函数

class Person():
    def __init__(self,name,age,list):
        self.name=name
        self.list=list
        self.age=age
    def __len__(self):
        return 10
    def __getitem__(self, index):
        return self.list[index]   

    def __call__(self):
        print(self.name)


person=Person("Stephen Curry",30,[1,2,3])
print(len(person))
print(person[0])
person()

结果:

10
1
Stephen Curry

魔法函数即使得调用实例方法时和一般的调用方法不太一样,可以让用户使用起来更加直观。比如在这里,可以像调用函数那样调用person实例,即实现了call函数里的内容。

而在深度学习的内容中,如果把图片存成一个列表,对于输入一个索引可以返回图片和标签,这样创造dataset后,用dataset[index](借助getitem函数)就可以利用索引访问相应图片和对应标签,便于dataloader进行加载处理。

同时借助len函数,如果返回值设置为数据集列表的长度,用len(dataset)就可以直观的得到数据集的大小。

2.类的私有属性和私有方法。

在面向对象设计程序时,类中的有些值我们不希望用户能够直接访问或修改,因此引用了私有属性,同理也有私有方法。类内可以访问,类外不能直接访问。而如果想要用户可以访问并修改值,我们可以在类内设计相应方法能够修改相应属性。

class Dog():
    def __init__(self,name):                     #init的函数的内容即在类的初始化时执行
        self.name=name
        self.__age=10                            #私有属性或私有方法前用__表示
        self.__func()                            #类中所有方法和属性的使用在不同函数之间都得加上self
    def modify_age(self,age):
        self.__age=age

    def show_age(self):
        print(self.__age)
    
    def __func(self):
        print("I am a dog")
        
    
dog=Dog('wang')
dog.modify_age(20)
dog.show_age()

结果:

I am a dog
20

可能不少人对此会产生疑惑,通过设置方法来对私有属性进行访问和修改,本质上和公共属性有什么区别呢,为何要这么麻烦?

从面向对象来理解,通过方法中设置一些判断语句,可以对用户输入的值进行限制以及提醒,更好地交互,也对用户的权限进行一定限制。这与直接设置为共有属性用户可以随意修改显然是不同的。

3.property属性

为了更直观的和用户交互,让用户调用方法就和访问属性一样,我们引入property属性

class Student:
    def __init__(self):
        self.__age=0
        
    @property                                                  
    def age(self):                              #可以直接用self.age调用,不用加括号,就像调用属性一样
        return self.__age                                          

    @age.setter                                 #可以直接用self.age=xxx 进行修改                        
    def age(self,a):
        self.__age=a       
        
    def show_age(self):
        print(self.__age)

给用户访问和修改私有属性提供了一种更直观的方式。

4.类方法和静态方法

class Dog:
    dogs=50
    @classmethod                             #类方法,用类直接进行调用,是类中共有的
    def num_of_dogs(cls):            
        cls.dogs=100                         #类方法中出现类属性要用cls.xxx
        


    @staticmethod
    def fun():                               #静态方法既可以用类来调用,也可以用实例对象来调用
        print("Dog is human's friends")   
    
    def __init__(self,name):   
        self.name=name
    def fun1(self,number):
        print(number)


Dog.num_of_dogs()
print(Dog.dogs)
dog=Dog('wang')
Dog.fun()
dog.fun()

结果:

100
Dog is human's friends
Dog is human's friends

类方法只能用类来调用,静态方法既可以用类来调用,也可以用实例对象来调用。

5.isinstance和issubclass——用来判断继承关系

#isinstance 用来判断a是不是A的实例对象   isinstance(a,A),返回bool类型
#issubclass 用来判断B是不是A的子类       issubclass(B,A) 返回bool类型       子类写在前,实例写在前,顺序不可颠倒
class A:
    pass
class B(A):
    pass
b=B()
a=A()
print(issubclass(B,A))
print(isinstance(b,B))
print(isinstance(b,A))              #特殊的,若有继承关系,则实例对象是它所有父类的实例对象
print(isinstance(a,B))

结果:

True
True
True
False

6.关于python包和模块的导入问题

下面是一个典型的python文件目录,其中若文件夹有__init__.py文件,则表示该文件夹整体为一个功能包,import时不用像普通模块那样写../../的地址,而是可以xxx.xxx用点的形式来写。

my_project/
    main_package/
        __init__.py
        another_sub_package/
            __init__.py
            other_module.py
        sub_package/
            __init__.py
            module.py
    main.py

如果采用绝对导入模块,对于上述例子如果想在main文件导入module.py,可以找到module.py所在的功能包,用import sub_package.module 当然也可以用from...import...的结构 。


如果采用相对导入,一般针对所导入的模块和当前文件在同一个功能包或者更上一级的功能包内,对于上述例子如果想在module.py中导入other_module.py,可以用..切换到上一级包,即from..another_sub_package importother_module
若是同级,可以import直接导入,也可以from . import ...
 

最后:方法中一定要记得加self!!!!!!!!!!!!!!!!!!!!!!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值