Python之旅的第3*7天(静态属性、类方法、静态方法、组合)
已经21天了,其实想感叹一下的,但是想起再没开始学之前,一位业界大神告诉我,你想学Python,以你的智商,一个周就能走上编程之路了,现在才发现,都是扯犊子啊。路只有自己走了才知道深浅,肉也只有长到自己身上了才知道我现在到底有多胖,不多说,省钱买新衣服吧。
今天主要讲的是类(class)的静态属性、类方法、静态方法和组合,应该算是功能的延伸吧,今天都是一些基础的引入。
一、静态属性的引入
# 关于静态属性的引入 # class Dog: # '引入静态属性的一个测试类' # type = '小土狗' # def __init__(self, name, gender, age): # self.name = name # self.gender = gender # self.age = age # # def yaoren(self): # print('%s正在咬人'%self.name) # 首先我们先生成一个实例对象 # p1 = Dog('alex','women',18) # 我们用p1去调用Dog类的数据属性,也就是type = '小土狗' # print(p1.type) # 而我们在调用yaoren这个功能属性的时候往往是这样的 # p1.yaoren() # 那么我们在后面运行的时候,通过调用的语句就能看出他到底是一个什么属性 # 这种情况是不利于软件封装的,因为在实际运用的过程中,yaoren其实也是一个固有的属性 # 而后面的括号,和直接运行的情况,很明显的将两者区分开了 # 这个时候我们引入了@property # 使用方法如下 class Dog: '引入静态属性的一个测试类' type = '小土狗' def __init__(self, name, gender, age): self.name = name self.gender = gender self.age = age @property def yaoren(self): return '%s正在咬人' % self.name # print('%s正在咬人' % self.name) # 经过了@property的修饰后,书写的方式和修饰器一毛一样 # 我们重新调用yaoren这个功能属性,方法就和调用数据属性的一样 p1 = Dog('alex','women',18) print(p1.yaoren) print(p1.type) # 这样在完成封装之后就便于类的统一,从外面是完全看不出来的
二、类方法
# 下面是类方法 # 换一个例子吧,就说一个智能手机的问题 # class Phone: # '关于类方法的一个测试,前面我们在查看一个类的功能属性,也就是类下面的函数功能时候, # '往往都是先实例化一个类的实例,然后调用对应的功能属性' # def __init__(self,pinpai, neicun, cpu): # self.pinpai = pinpai # self.neicun = neicun # self.cpu = cpu # # def paizhao(self,xiangsu): # print('%s的相机镜头用的是%s像素,拍照很厉害'%(self.pinpai,xiangsu)) # 首先是我们的常规套路 # 我们会先根据Phone类生成一个实例化的对象 # 然后再去调用拍照的方法 # p1 = Phone('小米','4G','骁龙865') # p1.paizhao('1亿') # 输出了:小米的相机镜头用的是1亿像素,拍照很厉害 # 但是生活中往往有很多人,打死不说品牌,就问你智能手机拍照牛不牛逼 # 反映到函数上就是,我们不生成一个实例化的对象,还能不能调用paizhao方法 # 我们在实际写类里面的函数的时候,往往会直接将self作为默认参数传人 # 所以,引入classmethod 将class作为默认参数传入 class Phone: # '关于类方法的一个测试,前面我们在查看一个类的功能属性,也就是类下面的函数功能时候, # '往往都是先实例化一个类的实例,然后调用对应的功能属性' def __init__(self,pinpai, neicun, cpu): self.pinpai = pinpai self.neicun = neicun self.cpu = cpu # @classmethod # def paizhao(self,xiangsu): # print('%s的相机镜头用的是%s像素,拍照很厉害'%(self.pinpai,xiangsu)) @classmethod def paizhao_test(cls,xiangsu): #此时括号内的默认参数就是cls print('智能手机的相机镜头用的是%s像素,拍照很厉害' % ( xiangsu)) # 增加了@classmethod之后我们就可以不生成实例化对象对拍照方法进行调用 Phone.paizhao_test('1亿') p1 = Phone('小米','4G','骁龙865') p1.paizhao_test('1亿') # 同时实例对象也可以调用 # 其实这个类的方法主要作用是用于显示类的信息 # 这里就得提到关于面向对象的类和生活中的类,还是存在区别的 # 显示类的信息就是程序员的编程需要 class Phone1: # '关于类方法的一个测试,前面我们在查看一个类的功能属性,也就是类下面的函数功能时候, # '往往都是先实例化一个类的实例,然后调用对应的功能属性' def __init__(self, pinpai, neicun, cpu): self.pinpai = pinpai self.neicun = neicun self.cpu = cpu # @classmethod # def paizhao(self,xiangsu): # print('%s的相机镜头用的是%s像素,拍照很厉害'%(self.pinpai,xiangsu)) def paizhao_test(self, xiangsu): # 此时括号内的默认参数就是cls print('智能手机的相机镜头用的是%s像素,拍照很厉害' % (xiangsu)) @classmethod def tell_info(cls): return Phone1.__dict__ # 类似是这样用的吧,我还是一直小菜鸡,说不清楚
三、静态方法(这里的静态方法实质上就是类的一个工具包,他的参数和self没有任何关系)
# 这里的静态方法实质上就是类的一个工具包,他的参数和self没有任何关系 # 这个地方我觉的还是以手机为例 # 引入静态方法的是增加@staticmethod class Telephone: '假设这是一个手机相关的类,但是诺基亚可以砸核桃' def __init__(self,name,xinghao): self.name = name self.xinghao =xinghao @staticmethod def zahetao(): print('我们诺基亚我牛逼') def calling(self): print('%s的%s在打电话'%(self.name,self.xinghao)) # 我们可以看到zahetao()这个功能属性其实并不需要传递self有关的参数 Telephone.zahetao() # 用类去调用这个方法没有问题 # p1 = Telephone('xiaomi','9se') # p1.zahetao() # 实例对象去调用也没有问题 # 但是此时如果我们不在zahetao()函数前面增加@staticmethod,也不传递参数,和加了的有什么区别呢 # 此时我隐去@staticmethod print(Telephone.__dict__) # 这个时候出现了一个问题 # p1.zahetao()这句代码报错了,报错内容如下 # zahetao() takes 0 positional arguments but 1 was given # 因为class会默认传递一个参数self,而我们的zahetao是不需要参数的 # 所以报错了 # 然后是关于此时Telephone的__dict__输出内容的问题 # {'__init__': <function Telephone.__init__ at 0x00000272C9064840>, 'calling': <function Telephone.calling at 0x00000272C9064950>, # '__dict__': <attribute '__dict__' of 'Telephone' objects>, '__weakref__': <attribute '__weakref__' of 'Telephone' objects>, # 'zahetao': <function Telephone.zahetao at 0x00000272C90648C8>, '__doc__': '假设这是一个手机相关的类,但是诺基亚可以砸核桃','__module__': '__main__'} # 这里我们注意字典中关于 zahetao()函数的描述是function #然后我们重新增加上@staticmethod的修饰 # {'calling': <function Telephone.calling at 0x000002D129824950>, '__weakref__': <attribute '__weakref__' of 'Telephone' objects>, # 'zahetao': <staticmethod object at 0x000002D129827B70>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'Telephone' # objects>, '__doc__': '假设这是一个手机相关的类,但是诺基亚可以砸核桃', '__init__': <function Telephone.__init__ at 0x000002D129824840>} # zahetao()函数的描述是staticmethod object # 所以发生了刚才p1调用失败的情况
四、组合
关于组合,其实就是将没有共同特点,但是又相关关联的类组合起来
# 这里的特点就类似与组装一个机器人,各个部件生产好了,然后组装在一起 # class Hand: # pass # # class Foot: # pass # # class Trunk: # pass # # class Head: # pass # # # class Person: # def __init__(self,id_num,name): # self.id_num=id_num # self.name=name # self.hand=Hand() # self.foot=Foot() # self.trunk=Trunk() # self.head=Head() # p1=Person('111111','alex') # print(p1.__dict__) # class School: # def __init__(self,name,addr): # self.name=name # self.addr=addr # # def zhao_sheng(self): # print('%s 正在招生' %self.name) # # class Course: # def __init__(self,name,price,period,school): # self.name=name # self.price=price # self.period=period # self.school=school # # # # s1=School('oldboy','北京') # s2=School('oldboy','南京') # s3=School('oldboy','东京') # # # c1=Course('linux',10,'1h','oldboy 北京') # c1=Course('linux',10,'1h',s1) # # print(c1.__dict__) # print(c1.school.name) # print(s1) class School: def __init__(self,name,addr): self.name=name self.addr=addr def zhao_sheng(self): print('%s 正在招生' %self.name) class Course: def __init__(self,name,price,period,school): self.name=name self.price=price self.period=period self.school=school s1=School('oldboy','北京') s2=School('oldboy','南京') s3=School('oldboy','东京') # c1=Course('linux',10,'1h','oldboy 北京') # c1=Course('linux',10,'1h',s1) msg=''' 1 老男孩 北京校区 2 老男孩 南京校区 3 老男孩 东京校区 ''' while True: print(msg) menu={ '1':s1, '2':s2, '3':s3 } choice=input('选择学校>>: ') school_obj=menu[choice] name=input('课程名>>: ') price=input('课程费用>>: ') period=input('课程周期>>: ') new_course=Course(name,price,period,school_obj) print('课程【%s】属于【%s】学校' %(new_course.name,new_course.school.name))
关于组合我理解的还是不够深刻,暂时先用这个了,明天我会增加自己的感悟的。
就是这样了,晚安。