内容简介:Python的面向对象
1. 进入 Python 的面向对象
python 作为一个弱类型的动态语言,其面向对象的方式与 Java 、C++这种强类型的语言相比还是有很大的不同的。其中Java、C++如何此处不作赘述。
首先,先预设这么一个类:
# code-01 class Person(object): def __init__(self, name): self.name = name def setName(self, name): self.name = name def getName(self): return self.name
像这样定义属性:
# code-02 def __init__(self, name): self.name = name # self.name 代表的就是定义的属性(先声明再定义?还是直接定义?由你决定!)
像这样定义函数:
# code-03 def setName(self, name): # 这里的setName()、getName()函数都可以通过实例来调用,self代表的是实例本身, # 其他函数的参数问题不在本文讨论之列,另外:注释不要像我这么写 self.name = name def getName(self): return self.name
2. 访问控制
python 的访问控制干脆直接,属性 权限 从属性的 名字 上即可得到。
此处按照常规的访问权限解释:
- public
如 code-01 的代码所示:
python # code-04 def __init__(self, name = '') self.name = name
这里的 self.name
就是 public
的,我们可以通过下面这种方式访问这个属性:
python # code-05 if __name__ == '__main__': p = Person("Marry") print(p.name) # 这里会输出: Marry
同样的,这里的 setName()
和 getName()
也是 public
的,我们也可以通过下面这种方式来访问:
python # code-06 if __name__ == '__main__': p = Person("Marry") print(p.getName()) # 这里会输出: Marry
- private
这里我们把上面 code-01
的代码修改 __init__(self,name)
函数,如下所示:
python # code-07 class Person(object): def __init__(self, name = "",marry = False): self.name = name self.__marry = marry
并添加如下代码,其他部分不变。
python # code-08 class Person(object): def __isMarry(self): return self.__marry
像 __isMarry(self)
这样的函数就是 private
函数, self.__marry
这样的属性(变量)就是 private
属性。
那么,如果再直接访问它的话,就会报错:
```python
# code-09
if name == ' main ':
p = Person("Marry")
print(p.getName()) # 这里会输出: Marry
print(p.__isMarry()) # 这里会报错
Traceback (most recent call last):
File "/media/somote/新加卷/pytest/ootest.py", line 16, in
- protected
事实上,python 并不提供这个权限,所以在此不作描述。
3. 内置装饰器
@property
先说一下property()函数,这里有必要提一下类的三个内置函数:setattr、getattr(以及getattribute)、delattr,关于关于这三个函数该如何使用,请自行搜索
property()的作用就在于把 setattr
、 getattr
、 delattr
三个函数给统一起来,如下所示:
# code-10 class Girl (Person): """ 我们新增一个 Girl 类,继承自 Person,同时我们为它新增一些身材属性 bust、waist、hip """ def __init__(self, name): super(Girl, self).__init__(name) self.bust = 80 self.waist = 80 self.hip = 80 # 这里的 figure 参数实际上就是*args(tuple类型) def setfigure(self, figure): self.bust, self.waist, self.hip = figure def getfigure(self): return self.bust, self.waist, self.hip def delfigure(self): del self.bust del self.waist del self.hip # 这里是重点 figure = property(getfigure, setfigure, delfigure)
运行:
# code-11 if __name__ == '__main__': g = Girl("Jane") print(g.name) g.setfigure((50,60,90)) # 通过函数来设置 print(g.getfigure())# 50,60,90 ''' 通过figure属性,绑定到其property()函数的 setter、getter、deller函数上,注意:这里必须把参数给齐,否则会报错 ''' g.figure = 60,90,90 print(g.figure) # 60,90,90 print(g.bust) # 60 print(g.waist) # 90 print(g.hip) # 90
我们也可以通过 @property
来设置属性:
# code-12 class Girl (Person): """ 我们新增一个 Girl 类,继承自 Person,同时我们为它新增一些身材属性 bust、waist、hip """ def __init__(self, name): super(Girl, self).__init__(name) self.bust = 80 self.waist = 80 self.hip = 80 # 这里预先把 figure() 装饰為 figure属性,所以可以在下面设置 setter、deleter,注意: getter 由这里的figure()代替了 @property def figure(self): print("get value") return self.bust, self.waist, self.hip @figure.setter def figure(self, figure): print("set value") self.bust, self.waist, self.hip = figure @figure.deleter def figure(self): del self.bust del self.waist del self.hip
运行:
# code-13 if __name__ == '__main__': g = Girl("Jane") print(g.name) # Jane g.figure = 60,90,90 # set value print(g.figure) # get value # 60,90,90 print(g.bust) # 60 print(g.waist) # 90 print(g.hip) # 90
通过 property()
或 @property
这种方式,可以控制某些属性的读写权限
@staticmethod
顾名思义, staticmethod
就是静态方法的意思,那么首先先来了解一下静态属性,在 code-12
的代码里,我们作如下修改:
# code-14 class Girl (Person): girlsnum = 0 # primary code here
运行:
# code-15 if __name__ == '__main__': g = Girl("Jane") print(g.girlsnum) # 1 g1 = Girl("Marry") print(g.girlsnum) # 2 g2 = Girl("Lucy") print(g1.girlsnum) # 3 print(Girl.girlsnum) # 3
可以看出, girlsnum 这个属性就是一个静态的类属性,那么 staticmethod 呢?
我们在 code-12 的基础上再次添加一些内容:
# code-16 class Girl (Person): # primary code here @staticmethod def info(name="", figure=()): return "Name : " + name + " \tFigure : " + str(figure)
然后运行:
# code-17 if __name__ == '__main__': g = Girl("Jane") print(Girl.info("Jane", g.figure)) # Name : Jane Figure : (80, 80, 80)
或许,你灵机一动把 info(name="", figure=())
改为 info(self,name="", figure=())
,那么去看看会发生什么吧![^1]
@classmethod
其实 @classmethod
和 @staticmethod
很难说到底有什么不同,水平有限,其具体用途留待探讨,此处只作简要说明。我们在 code-12
的基础上作如下修改:
# code-18 class Girl (Person): # primary code here @classmethod def build(clazz): print("ClassMethod")
运行:
# code-19 if __name__ == '__main__': g = Girl("Jane") Girl.build() # ClassMethod
注意:
-
@classmethod
所装饰的函数,最少需要一个参数,并且这个参数就是当前类本身 - 就调用而言, instancemethod_要宽泛于_staticmethod_和_classmethod (实例可以调用静态方法或者类方法,反之不可)
4. 某些属性
__dict__
__dict__
主要保存的是实例的属性键值对,我们对 code-12
的代码作如下修改并运行:
# code-20 if __name__ == '__main__': g = Girl("Jane") print(g.__dict__) # {'hip': 80, 'name': 'Jane', 'bust': 80, 'waist': 80}
注意: @property
所装饰的 figure
并没有作为属性被打印出来
__slots__
我们对 code-12 的代码作如下修改:
# code-07 class Girl (Person): __slots__ = ("bust", "waist", "hip") # primary code here
此时,Girl类应当只有三个属性: bust
、 waist
、 hip
了,但是事实并非如此,我们运行如下代码:
# code-21 if __name__ == '__main__': g = Girl("Jane") g.age = 25
发现仍能通过,并且通过 dir(g)
可以查看到age属性,为什么呢?
原因在于: Girl
的基类 Person
并没有用 __slots__
来限制属性,也就是说 __slots__
的作用范围仅仅包括当前类,所以:
# code-22 class Person(object): __slots__ = ("name") # primary code here
此时,再次运行 code-21 就会发现解释器会报错
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 面向Python,面向对象(基础)
- 面向Python,面向对象(基础3)
- <<深入PHP面向对象、模式与实践>>读书笔记:面向对象设计和过程式编程
- 《JavaScript面向对象精要》之六:对象模式
- 《JavaScript面向对象精要》之三:理解对象
- 面向对象的程序设计之理解对象
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。