python基础之面向对象(二)
一点提醒
首先在使用pickle读取load时,需要先把使用到的类import上,否则会报错.在pycharm中使用时不会报错,但在linux或者cmd时就会报错!必须import.
报错提示:
File "/Users/shane/PycharmProjects/Py_study/Base/S8/s9.py", line 8, in <module>
tt=pickle.load(open('test.pickle','rb'))
FileNotFoundError: [Errno 2] No such file or directory: 'test.pickle'
python编程时和Java C#一点区别
python中的函数参数可以是多种形态的.
Java和C#中,函数参数必须要指定类型;如果想向python中那样多种形态,要将参数指定为某类,参数可为类的子类或者派生类!
面向对象中的类成员
- 字段
- 方法
- 属性
字段
字段分为两种:
- 普通字段
- 静态字段
这里需要注意下的是,编程规范中,类名称一般需要首字母大写!
先来看段小程序吧:
class Province:
country='中国' #静态字段
def __init__(self,name):
self.name=name #普通字段
print(Province.country)
hn=Province('HN')
print(hn.country) #对象能访问,但一般不建议这么使用,建议使用类直接访问
普通字段我们使用的较多,一般是在构造方法时使用.
静态字段在代码加载时已经创建
字段 | 保存位置 | 规则 |
---|---|---|
普通字段 | 保存在对象中 | 只能用对象去访问 |
静态字段 | 保存在类中(节约内存空间) | 对象/类均可访问,但一般使用类访问,万不得已才使用对象访问) |
方法
所有方法都属于类,类基本可以分为三中类型:
- 普通方法
- 静态方法
- 类方法
方法 | 调用方式 | 特征 |
---|---|---|
普通方法 | 由对象去调用执行,属于类 | 至少一个self,对象调用 |
静态方法 | 属于类,但通过类来调用,不依赖于任何对象,方法内部不需要对象封装的值时,可使用静态方法 | 任意参数,没有self,上面添加@staticmethod,类似装饰器的东东 |
类方法 | 静态方法的一种特殊形式,由类调用 | 至少一个cls参数,上面添加classmethod |
来看两个例子吧:
静态方法:
class Province:
country='中国' #静态字段
def __init__(self,name):
self.name=name #普通字段
@staticmethod #静态方法
def show(arg1,arg2):
print(arg1,arg2)
print(Province.country)
hn=Province('HN')
print(hn.country)
Province.show(123,456)
类方法:
class Province:
country='中国' #静态字段
def __init__(self,name):
self.name=name #普通字段
@staticmethod #静态方法
def show(arg1,arg2):
print(arg1,arg2)
@classmethod
def f2(cls):
print(cls)
Province.f2()
out:
<class '__main__.Province'>
属性
属性的特征:具有方法的写作形式,具有字段的访问形式.可取值,可设置,可删除.
先来看看属性是个什么东西吧:
class Pager:
def __init__(self,all_count):
self.all_count=all_count
@property #定义属性
def all_pager(self):
a1,a2=divmod(self.all_count,10)
if a2==0:
return a1
else:
return a1+1
@all_pager.setter #赋值属性,将value赋值给方法的参数
def all_pager(self,value):
print(value)
@all_pager.deleter #删除属性
def all_pager(self):
print('del all_pager')
obj=Pager(101)
ret=obj.all_pager #不需要加括号
print(ret)
obj.all_pager=102
del obj.all_pager
属性的基本使用
属性的定义和调用需要注意以下几点:
- 定义时,在普通方法的基础上添加@property装饰器
- 定义时,属性仅有一个self参数
- 调用时,无需括号,obj.all_paper
属性存在的意义:访问属性时,可以制造出和访问字段完全相同的假象,由于属性是由方法变种而来,如果python中没有属性,完全可以由方法来替代.
属性的两种定义方式
python3中全都是新式类,有三种@property装饰方式:
- @property
- 方法名.setter
- 方法名.deleter
其实就像上面的例子.
还有一种方式是静态字段方式.创建值为property的对象的静态字段.
来看个例子:
class Pager:
def __init__(self,name):
self.name=name
def f1(self):
return 123
def f2(self,value):
print(value)
def f3(self):
print('del....')
foo=property(fget=f1,fset=f2,fdel=f3)
obj=Pager(110)
ret=obj.foo #调用fget
print(ret)
obj.foo=778 #调用fset
del obj.foo #调用fdel
输出结果:
123
778
del....
其中fget,fset,fdel为默认参数.
类成员修饰符
每个类成员的修饰符有两种:
- 公有成员:内部外部都能访问
- 私有成员:字段前面加两个_,比如:__cc,只有自己的类内部能访问,继承的父类,子类均不能访问.
class Foo:
__cc='cccccccccc'
def __init__(self,name):
self.__name=name
def f1(self):
print(Foo.__cc)
def f2(self):
print(self.__name)
@staticmethod
def __f3():
print('this is f3')
@staticmethod
def f4():
Foo.__f3()
# def
obj=Foo('alex')
# obj.f1() #正确
# obj.f2() #正确
# obj.__f3() #报错
obj.f4() #正确
# Foo.__f3() #报错
Foo.f4()
print(obj._Foo__cc) #能显示,但不建议这么做,万不得已不要这么使用
# print(obj.name) #报错
成员 | 字段/方法/属性 | 访问方式 |
---|---|---|
公有成员 | 静态 | 类可以访问;类内部可以访问;派生类中可以访问 |
公有成员 | 普通 | 对象可以访问;类内部可以访问;派生类中可以访问 |
私有成员 | 静态 | 仅类内部可以访问 |
私有成员 | 普通 | 仅类内部可以访问 |
print(obj._Foo__cc)
这种方式可以强制访问私有成员,但不符合规范...
类的特殊成员
python的类成员中有一部分特殊的存在.
__doc__ 表示类的描述信息,即注释
__module__ 表示当前操作的对象属于哪个模块
__class__ 表示当前操作的对象的类是什么
__init__ 构造方法
__del__ 析构方法,当对象在内存中被释放的瞬间执行(此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。)
__call__ 对象后面加括号,触发执行,例如:
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age def __call__(self, *args, **kwargs): #加括号执行
print("__call__") def __str__(self):
return '%s-%s'%(self.name,self.age) a=Foo('alex',19)
a()
out:
__call__
alex-18
__call__
__str__ 覆盖显示内存地址的内容,如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值。
__dict__ 类或对象中的所有成员,如果是类,返回的是对象的所有字段,如果是对象,返回所有成员,并且无论类或者对象,全部返回数据为字典类型.
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age def __call__(self, *args, **kwargs): #加括号执行
print("__call__") def __str__(self):
return '%s-%s'%(self.name,self.age) a=Foo('alex',19)
# a()
# print(a)
print(a.__dict__)
print(Foo.__dict__)
out:
{'name': 'alex', 'age': 19}
{'__doc__': None, '__str__': <function Foo.__str__ at 0x10127b7b8>, '__call__': <function Foo.__call__ at 0x10127b730>, '__init__': <function Foo.__init__ at 0x10127b6a8>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__dict__': <attribute '__dict__' of 'Foo' objects>}
alex-18
__call__
9. \_\_getitem__、\_\_setitem__、\_\_delitem__ 用于索引操作,对象后面加中括号"[]",将中括号中的参数传给item,来两个例子:
```python
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __getitem__(self, item):
if type(item)==str:
print(798)
return 798
elif type(item)==slice:
print(item.start)
print(item.stop)
print(item.step)
def __setitem__(self, key, value):
if type(key)==str:
print('setitem')
elif type(key)==slice and type(value)==list:
print(key.start)
print(key.stop)
print(key.step)
print(value)
def __delitem__(self, key):
if type(key)==str:
print('delitem')
elif type(key)==slice:
print(key.start)
print(key.stop)
print(key.step)
a=Foo('cc',23)
res=a[1:4:12]
print(res)
a[1:4]=[2,3,4,5]
del a[1:5]
```
输出:
```python
798
798
setitem
delitem
```
10. \_\_getslice__、\_\_setslice__、\_\_delslice__ 用于分片操作,看个例子:
```python
class Foo:
def __init__(self,name,age):
self.name=name
self.age=age
def __getitem__(self, item):
if type(item)==str:
print(798)
return 798
elif type(item)==slice:
print(item.start)
print(item.stop)
print(item.step)
def __setitem__(self, key, value):
if type(key)==str:
print('setitem')
elif type(key)==slice and type(value)==list:
print(key.start)
print(key.stop)
print(key.step)
print(value)
def __delitem__(self, key):
if type(key)==str:
print('delitem')
elif type(key)==slice:
print(key.start)
print(key.stop)
print(key.step)
a=Foo('cc',23)
res=a[1:4:12] #自动执行getslice
print(res)
a[1:4]=[2,3,4,5] #自动执行setslice
del a[1:5] #自动执行delslice
```
out:
```python
1
4
12
None
1
4
None
[2, 3, 4, 5]
1
5
None
```
11. \_\_iter__ 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 \_\_iter__,如果对象想被迭代,就得用此方法.
```python
class Foo:
def __iter__(self):
yield 1
yield 2
a=Foo()
for item in a:
print(item)
```
out:
```python
1
2
```
###自己写一个有序字典
利用上面的知识,我们可以自己写一个有序字典:
```python
class Mydict(dict):
def __init__(self):
self.li=[]
super(Mydict,self).__init__()
def __setitem__(self, key, value):
self.li.append(key)
super(Mydict,self).__setitem__(key,value)
def __str__(self):
temp_list=[]
for key in self.li:
value=self.get(key)
temp_list.append('"%s":%s'%(key,value))
temp_str='{'+','.join(temp_list)+'}'
return temp_str
d=Mydict()
d['a']=111
d['b']=222
print(d)
输出:
{"a":111,"b":222}
其他相关
isinstance(obj,cls) 检查obj是否是cls创建的对象
issubclass(cls1,cls2) 检查cls1是否是cls2的子类
super(cls,self).func() 主动执行父类的方法,看个例子:
class c1:
def f1(self):
print('c1.f1')
class c2(c1):
def f1(self):
super(c2,self).f1()
print('c2.f1')
#如果想主动执行c2父类的f1(),可以这么写
a=c2()
a.f1()
out:
c1.f1
c2.f1
此方法一般用来在不改变原代码的基础上做修改时使用此类方法即可.
单例模式
总结上面的知识,我们写一个单例模式吧,顾名思义,单例模式就是此模式只能创建一个实例,第一次创建一个模式,如果第二次创建是,返回还是第一个创建的实例或者对象,看代码吧:
class Foo:
instance=None
def __init__(self,name):
self.name=name
@classmethod
def get_instance(cls,value): #一般没value
if cls.instance:
return cls.instance
else:
obj=cls(value) #一般设定死
cls.instance=obj
return obj
obj1=Foo.get_instance('alex')
print(obj1)
obj2=Foo.get_instance('cc')
print(obj2)
输出:
<__main__.Foo object at 0x101a78ac8>
<__main__.Foo object at 0x101a78ac8>
python基础之面向对象(二)的更多相关文章
- 二十. Python基础(20)--面向对象的基础
二十. Python基础(20)--面向对象的基础 1 ● 类/对象/实例化 类:具有相同属性.和方法的一类人/事/物 对象(实例): 具体的某一个人/事/物 实例化: 用类创建对象的过程→类名(参数 ...
- Python 基础 四 面向对象杂谈
Python 基础 四 面向对象杂谈 一.isinstance(obj,cls) 与issubcalss(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls ...
- 自学Python之路-Python基础+模块+面向对象+函数
自学Python之路-Python基础+模块+面向对象+函数 自学Python之路[第一回]:初识Python 1.1 自学Python1.1-简介 1.2 自学Python1.2-环境的 ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- python基础,函数,面向对象,模块练习
---恢复内容开始--- python基础,函数,面向对象,模块练习 1,简述python中基本数据类型中表示False的数据有哪些? # [] {} () None 0 2,位和字节的关系? # ...
- python基础篇(二)
PYTHON基础篇(二) if:else,缩进 A:if的基础格式和缩进 B:循环判断 C:range()函数和len()函数 D:break,contiue和pass语句 for,while循环 函 ...
- python基础扩展(二)
python基础扩展(二) 常用操作 1.startswith(以什么开始) endswith(y)什么结束 s='taiWanw39dd' print(s.startswith('t')) #意思是 ...
- Day7 - Python基础7 面向对象编程进阶
Python之路,Day7 - 面向对象编程进阶 本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...
- Python基础7 面向对象编程进阶
本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个支持多用户在线的FTP程序 面向对象高级语法部分 经典 ...
随机推荐
- 1122 django中orm操作
目录 1. 静态文件的配置 手动静态文件的访问资源 静态文件的动态绑定 2.request方法 2.1 请求方式 2.2 获取前端的请求方式 request.method 2.3 request方法 ...
- python_面向对象——属性方法property
1.属性方法 class Student(object): def __init__(self,name): self.name = name @property #属性方法:把一个方法变成一个静态的 ...
- x006-函数和模块的使用
来源:百度SEO公司 函数和模块的使用 在Python中可以使用def关键字来定义函数,和变量一样每个函数也有一个响亮的名字,而且命名规则跟变量的命名规则是一致的.在函数名后面的圆括号中可以放置传递给 ...
- jquery.lazyload(懒加载)的使用与配置
jquery lazyload是一款基于jquery框架的图片延迟加载应用,它可以让用户访问页面的时候只显示当前屏幕所示的图片.原理为利用JS替换图片src为loading图片,新data-origi ...
- Substring Anagrams
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Strings ...
- Docker 学习10 Docker的系统资源限制及验证
一.资源限制 二.内存限制 1.OOME 每一个进程都会有oom_adj(oom计算分数的权重)值,此值越大,oom_score(oom得分)越高,越容易被干掉,因此非常非常重要的容器化应用,一开始就 ...
- 运行级别 runlevel
linux默认有7个等级,从0到6 0 关机 1 单用户模式,系统出现问题是可使用该模式进入系统.例如完了root密码,就可以使用1进入系统修改root密码 2 多用户模式,没有网络连接 3 完全多用 ...
- [English] - 单词阶段1
百词斩这个app很好玩,尤其是在记忆单词的时候,效果显著. 有的PK赛场也是比较谁的单词翻译提交的快,这个我曾经连胜好几次.
- CF455C Civilization
嘟嘟嘟 水题一道,某谷又恶意评分. 合并无非是将两棵树的直径的中点连一块,记原来两棵树的直径为\(d_1, d_2\),那么新的树的直径就是\(max(d_1, d_2, \lceil \frac{d ...
- selenium+chromeDriver配合使用(运行js脚本)
在python中调用selenium,访问百度,并运行js脚本爬取内容 python入口程序 from selenium import webdriver import time with open( ...