Python 抽象篇:面向对象之类的方法与属性
概览:
类成员之字段:
-普通字段,保存在对象中,执行职能通过对象访问
-静态字段,保存在类中,执行可以通过对象访问,也可以通过类访问
类成员之方法:
-普通方法,保存在类中,由对象来调用,self->对象
-静态方法,保存在类中,由类直接调用
-类方法,保存在类中,由类直接调用,cl->s当前类
应用场景:
如果对象中需要保存一些值,执行某功能时,需要使用对象中的值-->普通方法
不需要任何对象中的值-->静态方法
类成员之属性:property
1.类成员之字段
class Province:
country = '中国'#静态字段,属于类,跟对象没有关系,从上之下执行
def __init__(self,name):
self.name=name#普通字段,属于对象,通过对象访问
# sef.country='中国' henna=Province('河南')
hebei=Province('河北')
print(hebei.country) #中国
print(Province.country) #中国
print(hebei.name) #河北
静态字段在内存中只保存一份
普通字段在每个对象中都要保存一份
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
2.方法
class Bar:
def __init__(self,name,age):#self=z,name=greg,age=84
self.n=name
self.a=age
def foo(self):
print(self.n,self.a)
z=Bar('greg',25)
print(z.a)
z.foo()
创建方法
构造方法,__init__(self,arg)
obj = 类('a1')
普通方法
obj = 类(‘xxx’)
obj.普通方法名()
构造方法不同于其它方法之处在于:当一个对象被创建时,会立即调用构造方法,而且可以继承。
# -*- coding: utf-8 -*-
# 2017/12/3 13:50
class Foo:
def bar(self):#self是对象
print('bar')
print(self)#<__main__.Foo object at 0x000001E82A4D13C8>
@staticmethod
def sta():
print('') @staticmethod
def stas(a1,a2):#静态方法self不必须
print(a1,a2) @classmethod
def classmd(cls):#cls是类名
print('classmd')
print(cls) #<class '__main__.Foo'>
#普通方法
obj=Foo()
obj.bar() #bar
Foo.bar(obj ) #bar
#静态方法
obj.sta() #
obj.classmd()
Foo.sta() #
Foo.stas(1,2) #1,2
Foo.classmd()
"""
bar
<__main__.Foo object at 0x000001C83C765390>
bar
<__main__.Foo object at 0x000001C83C765390>
123
classmd
<class '__main__.Foo'>
123
1 2
classmd
<class '__main__.Foo'>
"""
普通方法:可以在实例化后直接调用,由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self,self.调用实例变量或类变量
类方法:由类调用; 实例也可调用,至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
静态方法:由类调用;实例也可调用,无默认参数;不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法
类变量定义在类的定义之后,实例变量则是以为self.开头,实例也能够访问类变量
class Foo(object):
val = 0
valu=2
def __init__(self):
self.val = 1 if __name__ == '__main__':
foo = Foo()
print(foo.val)#
print(foo.valu)#
print( Foo.val)#
没有init方式时
class Foo(object):
val = 0
def __init__(self):
pass
if __name__ == '__main__':
foo = Foo()
print(foo.val)#
print( Foo.val)#
还可以通过以下方式访问类变量
class Foo(object):
val = 3
def __init__(self):
print(self.__class__.val)
if __name__ == '__main__':
foo = Foo() #
类方法可以访问类变量
class Foo(object):
val = 3
def __init__(self):
pass @classmethod
def echo(cls):
print(cls.val)
if __name__ == '__main__':
Foo.echo()#
3.属性
新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
分别将三个方法定义为对同一个属性:获取、修改、删除
class Foo:
def __init__(self):
self.name='a'
self.name_list=['greg'] def bar(self):
print('bar') @property #属性
def per(self):
# print('124')
del self.name_list[0]
print(self.name_list)
return 123 @per.setter
def per(self,val):
print(val) @per.deleter
def per(self):
print(666) obj=Foo()
obj.bar() #bar
r=obj.per #[]
print(r) #
obj.per=345 #
del obj.per #
property的构造方法中有个四个参数,分别叫做:fget,fset,fdel ,doc
如果没有参数,产生的属性既不可读,也不可写
如果有一个参数,说明是取值方法,产生的属性是只读的。
第一个参数是方法名,调用 对象.属性 时自动触发执行方法
第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法,用于删除特性的方法
第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息,即文档字符串
class Foo:
def f1(self):
return 123 def f2(self,v):
print(v) def f3(self):
print('del') # per=property(fget=f1)#等同于下面三句
# @property
# def per(self):
# return 123 per = property(fget=f1,fset=f2,fdel=f3,doc='f4')
obj=Foo()
ret=obj.per
print(ret)
obj.per=12345
del obj.per
# print(obj.per.__doc__)
4.类的私有(private)特性
为了让方法或者特性变为 私有(从外部无法访问),只要在它的名字前面加上双下划线即可。
- 公有成员,在任何地方都能访问
- 私有成员,只有在类的内部才能方法
class Secretive:
def __inaccessible(self):
print("你看不到我") def accessible(self):
print("密码是:")
self.__inaccessible() s=Secretive()
# s.__inaccessible() #AttributeError: 'Secretive' object has no attribute '__inaccessible'
s.accessible()
# 密码是:
# 你看不到我
非要访问私有属性的话,可以通过 对象._类__属性名,比如Secretive._Secretive.__inaccessible
特殊成员
__init__() 构造方法 类()自动执行
__call__() 对象() 类()()自动执行
构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
print('__init__') def __call__(self, *args, **kwargs):
print('__call__') obj = Foo() # 执行 __init__
obj() # 执行 __call__
__str__ str()
class Foo:
def __init__(self,n,a):
self.name=n
self.age=a
def __str__(self):
return '%s-%s'%(self.name,self.age)
obj=Foo('greg',89)
print(obj) #print(str(obj)) str(obj)
__int__ int(对象)
class Foo:
def __init__(self):
pass
def __int__(self):
return 1111
def __str__(self):
return 'greg'
obj=Foo()
print(obj,type(obj))
#int,对象,自动执行对象的__init__方法,并将返回值赋值给int对象 r=int(obj)
print(r)
i=str(obj)
print(i)
__add__
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __add__(self, other):
self=obj1
other=obj2
# return self.age+other.age#37 <class 'int'>
return Foo('tt',99)#<__main__.Foo object at 0x0000017B7E2FC9B0> <class '__main__.Foo'> obj1=Foo('greg',19)
obj2=Foo('gregory',18)
r=obj1+obj2#两个对象相加时,自动执行第一个对象的__add__,
# 并且将第二个对象当做参数传递
print(r,type(r))
__dict__ 将对象中封装的所有内容通过字典的形式返回
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def show(self):
return "%s-%s"%(self.name,self.age) obj=Foo('greg',18)
print(obj.name) #greg
b="name"
print(obj.__dict__) #{'name': 'greg', 'age': 18}
print(obj.__dict__['name'])#greg
print(obj.__dict__[b])#greg
__getitem__切片(slice类型)或者索引,返回与所给键对应的值
__setitem__,按一定的方式存储于key相关的value
__delitem__,删除和key相关的键
class Foo(object):
def __getitem__(self, key):
print('__getitem__', key) def __setitem__(self, key, value):
print('__setitem__', key, value) def __delitem__(self, key):
print('__delitem__', key) obj = Foo()
result = obj['k1'] # 自动触发执行 __getitem__,输出__getitem__ k1
obj['k2'] = 'greg' # 自动触发执行 __setitem__,输出__setitem__ k2 greg
del obj['k1'] # 自动触发执行 __delitem__,输出__delitem__ k1
__iter__
# 如果类中有 __iter__ 方法,对象=》可迭代对象
# 对象.__iter__() 的返回值: 迭代器
# for 循环,迭代器,next
# for 循环,可迭代对象,对象.__iter__(),迭代器,next
# 1、执行li对象的类F类中的 __iter__方法,并获取其返回值
# 2、循环上一步中返回的对象
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __iter__(self):
return iter([11,22,33]) li=Foo('greg',18) #如果类中由__iter__方法,对象—》可迭代对象
#执行li对象的类Foo类中的__iter__方法
#循环上一步中的返回的对象 for i in li:
print(i)
__doc__
class Foo:
'描述'
""" 描述类信息 """
def func(self):
pass
print(Foo.__doc__)
#输出:描述
__module__ 和 __class__
__module__ 表示当前操作的对象在那个模块
__class__ 表示当前操作的对象的类是什么
from A.B import C obj = C()
print obj.__module__ # 输出A.B,即:输出模块
print obj.__class__ # 输出 A.B.C,即:输出类
__new__ 和 __metaclass__
class Foo:
def func(self):
print(123)
return 1 def function(self):
print(123) obj=Foo()
print(type(obj))#<class '__main__.Foo'>
print(type(Foo))#<class 'type'>
#obj对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建 Foo2=type('Foo2',(object,),{'func2':function})#声明一个类
obj2=Foo2()
obj2.func2()
#type第一个参数:类名,type第二个参数:当前类的基类,type第三个参数:类的成员
def func(self):
print("hello %s"%self.name) def __init__(self,name,age):
self.name = name
self.age = age
Foo = type('Foo',(object,),{'func':func,'__init__':__init__}) f = Foo("jack",22)
f.func()
加上构造方法
类 是由 type 类实例化产生
那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。
class MyType(type):
def __init__(self,*args,**kwargs):
#self=Foo类 self永远是类名
print(123)
pass def __call__(self, *args, **kwargs):
#self=Foo
print(456) class Foo(object,metaclass=MyType):#Foo是MyType的对象
def __init__(self):
print('Foo')
pass def __new__(cls, *args, **kwargs):
x=cls
return x def func(self):
print("hello world") obj=Foo() #加()是执行MyType的call方法,Foo里面要执行,要用call中的方法
#call不会调用Foo中init方法
结果:123
456

单下划线、双下划线、头尾双下划线说明:
__foo__: 定义的是特列方法,类似 __init__() 之类的。
_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
Python 抽象篇:面向对象之类的方法与属性的更多相关文章
- Python入门篇-面向对象概述
Python入门篇-面向对象概述 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.语言的分类 面向机器 抽象成机器指令,机器容易理解 代表:汇编语言 面向过程 做一件事情,排出个 ...
- 利用 Python 尝试采用面向对象的设计方法计算图形面积及周长
利用 Python 尝试采用面向对象的设计方法.(1)设计一个基类 Shape:包含两个成员函数:def cal_area(): 计算并返回该图形的面积,保留两位小数:def cal_perimete ...
- 【python学习笔记】9.魔法方法、属性和迭代器
[python学习笔记]9.魔法方法.属性和迭代器 魔法方法:xx, 收尾各有两个下划线的方法 __init__(self): 构造方法,创建对象时候自动执行,可以为其增加参数, 父类构造方法不会被自 ...
- python抽象篇:面向对象
1.面向对象概述 面向过程编程:根据操作数据的函数或语句块来设计程序的. 函数式编程:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象编程:数据和功能结合起来,用称为对象的东西包 ...
- python抽象篇:面向对象基础
1.面向对象概述 面向过程编程:根据操作数据的函数或语句块来设计程序的. 函数式编程:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象编程:数据和功能结合起来,用称为对象的东西包 ...
- python基础教程总结8——特殊方法,属性,迭代器,生成器,八皇后问题
1. 重写一般方法和特殊的构造方法 1.1 如果一个方法在B类的一个实例中被调用(或一个属性被访问),但在B类中没有找到该方法,那么会去它的超类A里面找. class A: ... def hello ...
- python基础学习笔记5--对象方法、属性和迭代器
对象方法.属性和迭代器 1.构造方法 1)构造方法和一般方法的不同点:当一个对象被创建后,会立即调用构造方法. 2)在Python中创建一个构造方法很容易,只要把init方法的名字从简单的init修改 ...
- Python 抽象篇:面向对象之高阶用法
1.检查继承 如果想要查看一个类是否是另一个类的子类,可以使用内建的issubclass函数 如果想知道已知类的基类,可以直接使用特殊特性__bases__ 同时,使用isinstance方法检查一个 ...
- python面向对象内置方法关于属性篇
1.关于__xxxattr__之__getattr__.__setattr__.__delattr__ 2.关于__xxxitem__之__getitem__.__setitem__.__delite ...
随机推荐
- Axios源码阅读笔记#1 默认配置项
Promise based HTTP client for the browser and node.js 这是 Axios 的定义,Axios 是基于 Promise,用于HTTP客户端--浏览器和 ...
- Kafka水位(high watermark)与leader epoch的讨论
~~~这是一篇有点长的文章,希望不会令你昏昏欲睡~~~ 本文主要讨论0.11版本之前Kafka的副本备份机制的设计问题以及0.11是如何解决的.简单来说,0.11之前副本备份机制主要依赖水位(或水印) ...
- 1 Spring Cloud Eureka服务治理(下)
注:此随笔为读书笔记.<Spring Cloud微服务实战> 上篇主要介绍了什么是微服务以及微服务治理的简单实现,如微服务注册中心的实现.微服务注册的实现.微服务的发现和消费的实现.微服务 ...
- angular学习笔记01
angular.js路由功能 用于实现单页应用 //html 代码 <div ng-view></div> //js代码 angular.module('myM1',['ng' ...
- java集合系列——Map之TreeMap介绍(九)
一.TreeMap的简介 TreeMap是一个有序的key-value集合,基于红黑树(Red-Black tree)的 NavigableMap实现.该映射根据其键的自然顺序进行排序,或者根据创建映 ...
- 微信支付之h5方式(非微信内置浏览器中支付)
这两天完成了公司网站手机和PC端的支付对接,就是支付宝和微信. 对接完后有所感触,我们来聊一聊,微信支付的坑,为什么这么说呢,因为我在对接完支付宝后是很愉快的,基本上在demo上稍加修改就ok了, 对 ...
- PyCharm基本操作
1.1 PyCharm基本使用 视频学习连接地址:http://edu.51cto.com/course/9043.html 1.1.1 在Pycharm下为你的Python项目配置Python解释器 ...
- html基础知识笔记
HTML基础 1.1HTML文件的基本结构和W3C标准 1.1.1HTML简介 HTML是一种描述网页的语言,一种超文本标记的语言! 1.1.2HTML文件的基本结构 头部(head) 头部是网页的标 ...
- java人员正确使用IDEA 的方式
博主是Java开发人员,以前一直都用myeclipse来开发的,说实话感觉myeclipse毫无美感可言,后来经过同事介绍,认识了IDEA,一眼就相中了IDEA黑色的主题风格,自此就抛弃了旧爱myec ...
- 解决子级用css float浮动 而父级div没高度不能自适应高度
解决子级对象使用css float浮动 而父级div不能自适应高度,不能被父级内容撑开解决方法,父级div没有高度解决方法. 最外层的父级DIV不能自适应高度-不能随对象撑开没有高度 当在对象内的盒子 ...