浅谈Python类的属性和方法

参考文献

在python中,有私有属性和公有属性,方法我们也一样,他们之间有何区别?

还有类属性和实例属性又是怎么回事?

静态方法和类方法又有什么区别?

我们在工作过程中,可能不太清楚,为什么要有私有属性,他们的意义何在?

我们对类的继承,对方法的重写又有哪些要注意的?

本着这些东西既然被设计出来了,就是为了我们更高效的工作这一角度,下面我从工作的角度,简单的说一下,这些点的区别:

xx: 公有变量
_x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问,也就是继承和调用
__xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到),既不能继承也不可以调用
__xx__:双前后下划线,用户名字空间的魔法对象或属性。例如:init , __ 不要自己发明这样的名字
xx_:单后置下划线,用于避免与Python关键词的冲突

我们在继承的时候什么继承不了,什么时候调用不了?

__xxx属性和方法都不可以继承及调用,但是类中其他类型的方法,可以调用__xxx的属性和方法,也可以被继承下来。

_xxx属性和方法 用from moudle import *的方法是无法导入的,但是,只要是子类就可以正常调用和继承,外部导入需要使用from moudle import _XXX

但是,注意,继承和调用是两码事

__xxx方法连调用都调用不了,完全的私有化

可以由如下代码解释:

#coding=utf-8class Person(object):# 定义类的一些属性GG = "niuniu"_name = "lala"__family = "tos"def __init__(self, name, age, taste):self.name = nameself._age = age self.__taste = tastedef showperson(self):print(self.name)print(self._age)print(self.__taste)def dowork(self):self._work()self.__away()def _work(self):print('my _work')def __away(self):print('my __away')class Student(Person):def construction(self, name, age, taste):self.name = nameself._age = age self.__taste = tastedef showstudent(self):print(self.name)print(self._age)print(self.__taste)@staticmethoddef testbug():_Bug.showbug()def squrt(self):self._work()print(self._name)# print(self.__family)self.__away()   ## 这块会报错,因为不能继承和调用父类的这种方法# 模块内可以访问,当from  cur_module import *时,不导入
class _Bug(object):@staticmethoddef showbug():print("showbug")s1 = Student('jack', 25, 'football')
s1.showperson()
print('*'*20)# 无法访问__taste,导致报错
# s1.showstudent()
s1.construction('rose', 30, 'basketball')
s1.showperson()
print('*'*20)s1.showstudent()
print('*'*20)Student.testbug()s1.squrt()print(Person.GG)print(Person._name)print(Person.__family)

Python中属性:类属性 、实例属性

掌握知识点: 什么事类属性什么事实例属性

类属性要通过什么方式进行修改,实例属性呢?

类属性如果通过实例的方式修改是不会生效的

在Python中的属性分为:类属性和对象(实例)属性:

1.类属性就是属于类所有,可以直接用类名.属性名直接调用,类的属性在内存中只有一份。实例属性就是在__init__()方法中初始化的属性;
2.实例属性属于类的对象所有,可以用对象名.属性名的形式进行调用,但是不能用类名.属性名进行调用 。因为实例属性只有在实例创建时,才会初始化创建。

#1.类属性和实例的属性的调用关系
class Person:country ="china"  #类属性def __init__(self,name,age):sex ="男"   #这不是实例属性,只是变量而已,用对象名.sex调不出来。self.name = name #实例属性self.age = age
#创建对象
print(Person.country)
#print(Person.age) 出错,AttributeError: type object 'Person' has no attribute 'age'
p1 = Person("tom",12)
print(p1.country,p1.age,p1.name,p1)----------结果如下------------------------------------------------------------------------
china
china 12 tom
----------------------------------------------------------------------------------------#2.修改类属性和实例属性:类属性只能通过类名.属性才可以修改
class Person:country ="china"  #类属性def __init__(self,name,age):sex ="男"   #这不是实例属性,只是变量而已,用对象名.sex调不出来。self.name = name #实例属性self.age = age-------创建对象-------------------------------------------------------------------------
p1.country = "america"
print(p1.country) #通过实例去修改属性,实例的属性修改了:america
print(Person.country)#但是类的属性还是没有修改:chinaPerson.country = "japan" #只有用类名.属性名才能修改类的属性值。
p2= Person("jack",11)
print("p1.country:",p1.country)
print("p2.country",p2.country)
print("Person.country",Person.country)
------结果如下-----------------------------------------------------------------------------
america
china
p1.country: america
p2.country japan
Person.country japan

实际开发中为了程序的安全,关于类的属性都会封装起来,Python中为了更好的保存属性安全,即不能随意修改。一般属性的处理方式为:1.将属性定义为私有属性。2.添加一个可以调用的方法,供调用。

class Person1(object):country ='china' #类属性__language ="Chinese" #私有类属性也不能直接外部调用def __init__(self,name,age):self.name = nameself.__age = age  #使用__下划线表示私有属性,对象不能直接调用,要通过方法调调用def getAge(self):return self.__agedef setAge(self,age):if age >100 or age <0:print("age is not true")else :self.__age = agedef __str__(self):info = "name :"+self.name +",age(保密):"+str(self.__age)  #注意这里不是self.agereturn info#------创建对象,调用方法,属性测试-------------------------------------------------------
stu1 =  Person1("tom",18)
print("修改前的结果:",stu1.__str__())
stu1.name="tom_2"  #修改stu1的name属性
print("修改name后的结果:",stu1.__str__())
#print(stu1.__age)  #直接调用私有属性__age报错,'Person1' object has no attribute '__age'print("打印私有age内存地址:",id(stu1.getAge()))
stu1.__age = 19  #如果这样赋值的话,不会报错,因为系统找不到这个变量,直接新建了一个。但是实际没有修改对象的属性值
print(stu1.__age) #有值,但是没有 实际修改stu1对象的age属性值
print("打印stu1.__age的内存地:",id(stu1.__age)) #两个内存地址值不一样。
print("错误修改age后的值",stu1.__str__())  #实际值没有变stu1.setAge(22) #只有调用才可以修改age的值
print("正确修改age后的值",stu1.__str__())'''执行结果如下:
修改前的结果: name :tom,age(保密):18
修改name后的结果: name :tom_2,age(保密):18
打印私有age内存地址: 1388146224
19
打印stu1.__age的内存地: 1388146256
错误修改age后的值 name :tom_2,age(保密):18
正确修改age后的值 name :tom_2,age(保密):22
'''

私有方法,类方法,静态方法的使用

静态的方法,看起来,这个方法好像不太明白什么意思,其实类似于java语言中的静态方法

也就是说,这个方法,其实不依赖类创建出来的实例,而是说,我们可以独立成一个函数,只不过呢,我们放在类里面是比较方便的,仅此而已。调用的话,直接用类+函数名或者实例+函数名调用

类方法,我们调用的时候,直接用类名+函数名调用就可以了,至于适用的场景,我没想到呢。有一个场景,就是用来修改类属性,但是修改类属性,有什么用呢?我们为什么要修改类的属性。

1.私有方法:以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用他),不能在类地外部调用。

class Person5:def __p(self):print("这是私有属性") #内部函数也同样可以任意之间互相调用def p1(self):print("这是p1不是私有方法")def p2(self):print("这是p2,可以调用p1,也可以调用私有方法__p")self.p1()self.__p()
#创建对象
c1 = Person5()
c1.p1()
c1.p2()
#c1.__p() #不能直接私有函数。报错。注意区分系统自带的函数如__str__,外部可以直接调用的。'''结果如下:
这是p1不是私有方法
这是p2,可以调用p1,也可以调用私有方法__p
这是p1不是私有方法
这是私有属性
'''

2.类方法的使用:是类所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,也可以有别的参数。但是第一个必须是类对象,类似类中的def定义的普通方法第一个参数要是self一样的道理

class People(object):country = 'china'#类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用@classmethoddef getCountry(cls):return cls.country@classmethoddef sum(cls,a,b):return a+b        p = People()
print (p.getCountry())  #可以用过实例对象引用
print (People.getCountry() )   #可以通过类名.方法名的形式调用
print(p.sum(10,11))
print(People.sum(10,11))
====================================================================================
china
china
21
21
3.静态方法:需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数 class People(object):country = 'china'@staticmethod#静态方法,不用定义参数def getCountry():return People.countryprint (People.getCountry())

3.方法的使用注意要点
注意python中不支持方法的重载:即方法名相同,参数类型(参数个数不同)不同的函数,python中 不支持。

def p():print("dd")
def p(a,b):print("dd")def p(a):print("dd")
p()#报错,因为python中不需要定义参数的类型。如果有多个重载的函数,则python默认只能使用最后一个有效。
所以只能调用P(a)这个函数

property的魔法函数使用及场景

参考文献:https://blog.csdn.net/jpch89/article/details/84026130

class Student:def __init__(self):self._age = None@propertydef age(self):print('获取属性时执行的代码')return self._age@age.setterdef age(self, age):print('设置属性时执行的代码')self._age = age@age.deleterdef age(self):print('删除属性时执行的代码')del self._agestudent = Student()# 设置属性
student.age = 18
"""
设置属性时执行的代码
"""# 获取属性
print('学生年龄为:' + str(student.age))
"""
获取属性时执行的代码
学生年龄为:18
"""# 删除属性
del student.age
"""
删除属性时执行的代码
"""

类继承的相关问题

参考文献:https://blog.csdn.net/yilulvxing/article/details/85374142

这一部分,我们要掌握:

  • 继承的话,哪些可以继承,哪些又不能继承呢?

首先,记住我们上面的原则,只要是__xxx的类型和属性就不可以被继承和调用

  • 多继承的话,有什么顺序吗?我们怎么判断。

比如C(A,B)。那么,大小顺序如下:

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.base'>, <class 'object'>)

  • 父类方法的重写
#coding=utf-8
class Cat(object):def sayHello(self):print("halou-----1")class Bosi(Cat):def sayHello(self):print("halou-----2")bosi = Bosi()bosi.sayHello()
  • 父类方法的调用

推荐使用下面两种方式之一

super().__init__( a, b)
# Father.__init__(self, a, b)
class Father():def __init__(self,a,b):self.a = aself.b = bdef dev(self):return self.a - self.b#调用父类初始化参数a,b并增加额外参数c
class Son(Father):def __init__(self,a,b,c=10):  # 固定值: 例如默认c=10,也可以显式地将c赋值Father.__init__(self,a,b)  self.c = cdef add(self):return self.a+self.bdef compare(self):if self.c > (self.a+self.b):return Trueelse:return Falseson=Son(1,2,1)     #  显式地将c=1传入子类初始化函数
print(son.dev())     # 调用父类dev函数
print(son.add())     # 子类自身add函数
print(son.compare()) # 子类自身compare函数
  • 在初始化的过程中,如果我们__init__初始化,应该如何继承
#coding=utf-8
class Cat(object):def __init__(self,name):self.name = nameself.color = 'yellow'class Bosi(Cat):def __init__(self,name):# 调用父类的__init__方法1(python2)#Cat.__init__(self,name)# 调用父类的__init__方法2#super(Bosi,self).__init__(name)# 调用父类的__init__方法3super().__init__(name)def getName(self):return self.namebosi = Bosi('xiaohua')print(bosi.name)
print(bosi.color)

单例模式

单例模式的实现,需要借助__new__方法。

单例模式的应用

  1. 保证只有一个对象
# 实例化一个单例
class Singleton(object):__instance = Nonedef __new__(cls, age, name):#如果类数字能够__instance没有或者没有赋值#那么就创建一个对象,并且赋值为这个对象的引用,保证下次调用这个方法时#能够知道之前已经创建过对象了,这样就保证了只有1个对象if not cls.__instance:cls.__instance = object.__new__(cls)return cls.__instancea = Singleton(18, "dongGe")
b = Singleton(8, "dongGe")print(id(a))
print(id(b))a.age = 19 #给a指向的对象添加一个属性
print(b.age)#获取b指向的对象的age属性
  1. 创建单例时,只执行一次init方法
# 实例化一个单例
class Singleton(object):__instance = None__first_init = Falsedef __new__(cls, age, name):if not cls.__instance:cls.__instance = object.__new__(cls)return cls.__instancedef __init__(self, age, name):if not self.__first_init:self.age = ageself.name = nameSingleton.__first_init = Truea = Singleton(18, "dongGe")
b = Singleton(8, "dongGe")print(id(a))
print(id(b))print(a.age)
print(b.age)a.age = 19
print(b.age)

浅谈Python类的属性和方法相关推荐

  1. python编程是干啥用的-浅谈Python类中的self到底是干啥的

    Python编写类的时候,每个函数参数第一个参数都是self,一开始我不管它到底是干嘛的,只知道必须要写上.后来对Python渐渐熟悉了一点,再回头看self的概念,似乎有点弄明白了. 首先明确的是s ...

  2. Python—类私有化属性和方法

    目录 一.私有化属性 语法 特性 特性-1 特性-2 特性-3 二.私有化方法 语法 示例 特性 三.Property属性 实现方式 实现方式-1 示例 实现方式-2 一.私有化属性 语法: 两个下划 ...

  3. python类中方法的执行顺序-浅谈Python的方法解析顺序(MRO)

    方法解析顺序, Method Resolution Order 从一段代码开始 考虑下面的情况: class A(object): def foo(self): print('A.foo()') cl ...

  4. python中怎么调用函数_浅谈Python中函数的定义及其调用方法

    一.函数的定义及其应用 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用函数的使用包含两个步骤 1.定义函数–封装独立的功能 2.调用函数–享受封装的成果 函数的作用:在开发时 ...

  5. python方法解析顺序_浅谈Python的方法解析顺序(MRO)

    方法解析顺序, Method Resolution Order 从一段代码开始 考虑下面的情况: class A(object): def foo(self): print('A.foo()') cl ...

  6. python函数定义及调用-浅谈Python中函数的定义及其调用方法

    一.函数的定义及其应用 所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用函数的使用包含两个步骤 1.定义函数�C封装独立的功能 2.调用函数�C享受封装的成果 函数的作用:在开 ...

  7. python新式类和旧式类的区别_浅谈python新式类和旧式类区别

    python的新式类是2.2版本引进来的,我们可以将之前的类叫做经典类或者旧式类. 为什么要在2.2中引进new style class呢?官方给的解释是: 为了统一类(class)和类型(type) ...

  8. python static方法_浅谈python 类方法/静态方法

    1.类方法 类方法是从属于"类对象"的方法.类对象可以通过装饰器@classmethod来定义,具体格式如下: @classmethod def 类方法名(cls [, 形参列表] ...

  9. python脚本开头怎么写_浅谈Python脚本开头及导包注释自动添加方法

    浅谈Python脚本开头及导包注释自动添加方法 1.开头:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用 – 指定 #!/usr/bin/python 是用来 ...

最新文章

  1. Vista下的程序集缓存卸载方法,也就是C:\Windows\assembly之下的卸载方法
  2. isinstance函数和@staticmethod用法
  3. stm32-USART1重映射
  4. xtrabackup mysql 5.6_MySQL 5.6对于Xtrabackup的影响
  5. new Date()时间
  6. js设置控制滚动条位置
  7. 蚂蚁金服冯柯:下一个十年,核心自研技术将迎来黄金发展期
  8. 服务器ftp网站怎么临时关闭,如何停止pyftpdlib FTP服务器?
  9. 安装nginx之前的组件
  10. IDEA 的这款插件真是逆天了,代码那都不是事!
  11. 【御数·原创】数据治理的坑你遇到过几个?
  12. 三次样条插值的缺点_三次样条插值
  13. Web—信息收集(非常全)
  14. 网站优化提高网站关键词密度是必要的
  15. 下载网易云音乐的MV
  16. Objective-C简介
  17. C语言编程求小球自由落体高度
  18. 物联网项目(四)订单系统
  19. 【luoguP5550】Chino的数列
  20. webUpload上传附件

热门文章

  1. 用python制作生日蛋糕图片大全_Python 制作微信全家福,你就是朋友圈最亮的仔!...
  2. 数据挖掘标准流程CRISP-DM
  3. 关于ITSS的一些问答......
  4. OpenHarmonyOs / LiteOs-a 驱动开发
  5. php茶餐厅销售管理系统的设计与实现
  6. 浪漫烟花——C/C++
  7. cef离屏渲染(osr)初识
  8. 计算机二战一个双非学校怎样,双非二战学长成功调剂985:看他的调剂院校选择!...
  9. Arduino ESP8266 创建OneNet设备(二)
  10. java 从已知日期计算干支纪日_干支纪日在线换算(干支纪日从何时开始)