python进阶之路,你必须熟练掌握的关于类的用法

前言

这篇文章将系统带大家了解python类中一些进阶的用法,不敢保证能把理论介绍清晰,但也尽量把用法表达的生动明了。

类的继承

简单的继承

class Person:   # 定义一个父类
 
    def talk(self):    # 父类中的方法
        print("person is talking....") 


class Cooker(Person):
    def walk(self):
        print("make malatang")
cooker = Cooker()
cooker.talk()
cooker.walk()
person is talking....
make malatan

类方法的重写

class Person:   # 定义一个父类
 
    def talk(self):    # 父类中的方法
        print("person is talking....") 


class Cooker(Person):
    def talk(self):
        print("Cooker is talking....")
cooker = Cooker()
cooker.talk()
Cooker is talking....

构造函数的继承

class Person:
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.weight = 'weight'
 
    def talk(self):
        print("person is talking....")
 
 
class Chinese(Person):
 
    def __init__(self, name, age, language):  # 先继承,在重构
        super(Chinese, self).__init__(name, age)  #继承父类的构造方法,也可以写成Person.__init__(self, name, age) 这种继承在单继承中没有问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题
        self.language = language    # 定义类的本身属性
 
    def walk(self):
        print('say {}'.format(self.language))
c = Chinese("嘎子", 22, "卧槽")
c.walk()
c.talk()
say 卧槽
person is talking....

类中的特殊方法

classmethod

我们先来看下classmethod函数的用法

class Test_Staic:
    def __init__(self):
        print("实例化测试类")

    @classmethod
    def say_hello(cls, name):
        print("hello: ", name)
Test_Staic().say_hello("小强")
实例化测试类
hello:  小强

我们可以看到类被实例化,然后调用了类方法。这是很正常的使用。

Test_Staic.say_hello("小强")
hello:  小强

我们发现类有没有被实例化都可以调用被classmethod装饰的函数。但是如果只是这样的话,好像跟staticmethod并没有什么区别。

其实我们也称呼classmethod为构造方法。

class Data_test:
    def __init__(self,year=0,month=0, day=0):
        self.day = day
        self.month = month
        self.year = year

    def out_date(self):
        print("day", self.day)
        print("month", self.month)
        print("year", self.year)
data_test = Data_test(2021, 5, 8)
data_test.out_date()
day 8
month 5
year 2021

这是一个表现时间的对象,我们实例化输入的是具体年月日。但如果我们输出的不是这种标准的格式呢,比如是这种"2021-5-8", 这样我们怎么办呢。我们可以在实例化时加入一个其他参数,来处理。但这样无疑使我们的对象变得臃肿。

这样无疑是变得无意义的。

class Data_test2:
    def __init__(self, year=0, month=0, day=0):
        self.day = day
        self.month = month
        self.year = year

    def out_date(self):
        print("day", self.day)
        print("month", self.month)
        print("year", self.year)

    @classmethod
    def separate(cls, data_string):
        year, month, day = data_string.split("-")
        return cls(year, month, day)
data_test = Data_test2.separate("2021-5-8")
data_test.out_date()
day 8
month 5
year 2021

这样就相当于给我们的类加了一个新的实例方法。

还有一点需要注意的是我们的classmethod方法无法使用实例属性,甚至在使用方法也比较繁琐。但是却可以调用静态方法。

staticmethod

class Test_Staic:
    def __init__(self):
        print("实例化测试类")

    @staticmethod
    def say_hello(name):
        print("staticmethod: ", name)
Test_Staic().say_hello("hello")
Test_Staic.say_hello("hello")
实例化测试类
staticmethod:  hello
staticmethod:  hello

staticmethod与classmethod的相同点是都是既是类方法也是实例方法,不同点是staticmethod装饰的就是一个类方法而已,和外部函数没有任何区别。

甚至我觉得如无必要,在类中加入过多的staticmethod本身就是不好的。一个类中如果有过多的静态方法,这个类本身写的也算不上高明。

property

class Student:
    def __init__(self):
        self._birth = 1997
    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2021 - self._birth
stu = Student()
stu.birth
1997
stu.age
24

我们可以看到,我们使用property装饰一个名为age的函数,他返回的是这个实例的年龄。这样该函数就能如属性一样调用。

在实际开发中,动态属性函数的内部实现可能会更加复杂。

之所以我们称呼动态属性,是因为我们可以进行动态的取值以及赋值。

stu.birth = 2008
stu.birth
2008
stu.age
13

是不是感觉这一套操作行云流水

类中的私有属性及方法

私有属性

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.__age = age  #使用__下划线表示私有属性,对象不能直接调用,要通过方法调调用
 
    def getAge(self):
        return self.__age
 
    def setAge(self,age):
        if age >100 or age <0:
            print("age is not true")
        else :
            self.__age = age
 
    def __str__(self):
        info = "name :"+self.name +",age:"+ str(self.__age)
        return info
per =  Person("kangkang", 22)
print(per)
name :kangkang,age:22
per._age
AttributeError: 'Person' object has no attribute '_age'

直接调用则会报错,我们尝试赋值

per._age = 88
print(per)
name :kangkang,age:22

其实私有属性的值并没有被改变

per.setAge(88)
print(per)
name :kangkang,age:88

只有通过内部的函数才能调用该属性。但是其实我们在团队开发中应避免使用__方法名这种方式,而采用 _方法名,这种虽然不是强制性的,但一种建议性的命名,往往在开发中更能被接受。

私有方法

class Person2:
    def __f1(self):
        print("这是私有方法")
    def f2(self):
        print("这是f2不是私有方法")
    def f3(self):
        print("这是f3,可以调用f2,也可以调用私有方法__f1")
        self.f2()
        self.__f1()
per = Person2()
per.__f1()
AttributeError: 'Person2' object has no attribute '__f1'

同样私有方法外部不可以调用。

per.f3()
这是f3,可以调用f2,也可以调用私有方法__f1
这是f2不是私有方法
这是私有方法

让实例变得可迭代

class City:
    def __init__(self, city_list):
        self.city_list = city_list
    def __getitem__(self, index):
        return self.city_list[index]
city = City(['北京', '成都', '杭州'])
city[2]
'杭州'
for i in city:
    print(i)
北京
成都
杭州
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值