文章目录
- 前言
- 一、成员
- 1.1 变量
- 1.2 方法
- 1.3 属性
- 二、成员修饰符
- 三、对象嵌套
- 四、特殊成员
- 关于Python技术储备
- 一、Python所有方向的学习路线
- 二、Python基础学习视频
- 三、精品Python学习书籍
- 四、Python工具包+项目源码合集
- ①Python工具包
- ②Python实战案例
- ③Python小游戏源码
- 五、面试资料
- 六、Python兼职渠道
前言
通过面向对象进行编程时,会遇到很多种情况,也会使用不同的成员来实现,接下来我们来逐一介绍成员特性和应用场景,需要的朋友可以参考下
一、成员
1.1 变量
- 实例变量,属于对象,每个对象中各自维护自己的数据。
- 类变量,属于类,可以被所有对象共享,一般用于给对象提供公共数据(类似于全局变量)。
class Person(object):
country = "中国"
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
def show(self):
# message = "{}-{}-{}".format(Person.country, self.name, self.age)
message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) # 中国
p1 = Person("华青水上",20)
print(p1.name)
print(p1.age)
print(p1.country) # 中国
p1.show() # 中国-华青水上-20
**提示:**当把每个对象中都存在的相同的示例变量时,可以选择把它放在类变量中,这样就可以避免对象中维护多个相同数据。
易错点
- 注意读和写的区别。
class Person(object):
country = "中国"
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) # 中国
p1 = Person("华青水上",20)
print(p1.name) # 华青水上
print(p1.age) # 20
print(p1.country) # 中国
p1.show() # 中国-华青水上-20
p1.name = "root" # 在对象p1中讲name重置为root
p1.num = 19 # 在对象p1中新增实例变量 num=19
p1.country = "china" # 在对象p1中新增实例变量 country="china"
print(p1.country) # china
print(Person.country) # 中国
class Person(object):
country = "中国"
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) # 中国
Person.country = "美国"
p1 = Person("华青水上",20)
print(p1.name) # 华青水上
print(p1.age) # 20
print(p1.country) # 美国
- 继承关系中的读写
class Base(object):
country = "中国"
class Person(Base):
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(Person.country, self.name, self.age)
# message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
# 读
print(Base.country) # 中国
print(Person.country) # 中国
obj = Person("华青水上",19)
print(obj.country) # 中国
# 写
Base.country = "china"
Person.country = "泰国"
obj.country = "日本"
1.2 方法
- 绑定方法,默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象&类均可调用】
- 类方法,默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象&类均可调用】
- 静态方法,无默认参数,用类和对象都可以调用。【对象&类均可调用】
class Foo(object):
def \_\_init\_\_(self, name,age):
self.name = name
self.age = age
def f1(self):
print("绑定方法", self.name)
@classmethod
def f2(cls):
print("类方法", cls)
@staticmethod
def f3():
print("静态方法")
# 绑定方法(对象)
obj = Foo("武沛齐",20)
obj.f1() # Foo.f1(obj)
# 类方法
Foo.f2() # cls就是当前调用这个方法的类。(类)
obj.f2() # cls就是当前调用这个方法的对象的类。
# 静态方法
Foo.f3() # 类执行执行方法(类)
obj.f3() # 对象执行执行方法
在Python中比较灵活,方法都可以通过对象和类进行调用;而在java、c#等语言中,绑定方法只能由对象调用;类方法或静态方法只能由类调用。
import os
import requests
class Download(object):
def \_\_init\_\_(self, folder\_path):
self.folder\_path = folder\_path
@staticmethod
def download\_dou\_yin():
# 下载抖音
res = requests.get('.....')
with open("xxx.mp4", mode='wb') as f:
f.write(res.content)
def download\_dou\_yin\_2(self):
# 下载抖音
res = requests.get('.....')
path = os.path.join(self.folder\_path, 'xxx.mp4')
with open(path, mode='wb') as f:
f.write(res.content)
obj = Download("video")
obj.download\_dou\_yin()
1.3 属性
属性其实是由绑定方法 + 特殊装饰器 组合创造出来的,让我们以后在调用方法时可以不加括号。
class Foo(object):
def \_\_init\_\_(self, name):
self.name = name
def f1(self):
return 123
@property
def f2(self):
return 123
obj = Foo("华青水上")
v1 = obj.f1()
print(v1)
v2 = obj.f2
print(v2)
class Pagination:
def \_\_init\_\_(self, current\_page, per\_page\_num=10):
self.per\_page\_num = per\_page\_num
if not current\_page.isdecimal():
self.current\_page = 1
return
current\_page = int(current\_page)
if current\_page < 1:
self.current\_page = 1
return
self.current\_page = current\_page
def start(self):
return (self.current\_page - 1) \* self.per\_page\_num
def end(self):
return self.current\_page \* self.per\_page\_num
user\_list = \["用户-{}".format(i) for i in range(1, 3000)\]
# 分页显示,每页显示10条
while True:
page = input("请输入页码:")
# page,当前访问的页码
# 10,每页显示10条数据
# 内部执行Pagination类的init方法。
pg\_object = Pagination(page, 20)
page\_data\_list = user\_list\[ pg\_object.start() : pg\_object.end() \]
for item in page\_data\_list:
print(item)
class Pagination:
def \_\_init\_\_(self, current\_page, per\_page\_num=10):
self.per\_page\_num = per\_page\_num
if not current\_page.isdecimal():
self.current\_page = 1
return
current\_page = int(current\_page)
if current\_page < 1:
self.current\_page = 1
return
self.current\_page = current\_page
@property
def start(self):
return (self.current\_page - 1) \* self.per\_page\_num
@property
def end(self):
return self.current\_page \* self.per\_page\_num
user\_list = \["用户-{}".format(i) for i in range(1, 3000)\]
# 分页显示,每页显示10条
while True:
page = input("请输入页码:")
pg\_object = Pagination(page, 20)
page\_data\_list = user\_list\[ pg\_object.start : pg\_object.end \]
for item in page\_data\_list:
print(item)
关于属性的编写有两种方式:
- 方式一,基于装饰器
class C(object):
@property
def x(self):
pass
@x.setter
def x(self, value):
pass
@x.deleter
def x(self):
pass
obj = C()
obj.x
obj.x = 123
del obj.x
- 方式二,基于定义变量
class C(object):
def getx(self):
pass
def setx(self, value):
pass
def delx(self):
pass
x = property(getx, setx, delx, "I'm the 'x' property.")
obj = C()
obj.x
obj.x = 123
del obj.x
**注意:**由于属性和实例变量的调用方式相同,所以在编写时需要注意:属性名称 不要 实例变量 重名。
class Foo(object):
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
@property
def func(self):
return 123
obj = Foo("华青水上", 123)
print(obj.name)
一旦重名,可能就会有报错。
class Foo(object):
def \_\_init\_\_(self, name, age):
self.name = name # 报错,错认为你想要调用 @name.setter 装饰的方法。
self.age = age
@property
def name(self):
return "{}-{}".format(self.name, self.age)
obj = Foo("华青水上", 123)
class Foo(object):
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
@property
def name(self):
return "{}-{}".format(self.name, self.age) # 报错,循环调用自己(直到层级太深报错)
@name.setter
def name(self, value):
print(value)
obj = Foo("华青水上", 123)
print(obj.name)
如果真的想要在名称上创建一些关系,可以让实例变量加上一个下划线。
class Foo(object):
def \_\_init\_\_(self, name, age):
self.\_name = name
self.age = age
@property
def name(self):
return "{}-{}".format(self.\_name, self.age)
obj = Foo("华青水上", 123)
print(obj.\_name)
print(obj.name)
二、成员修饰符
Python中成员的修饰符就是指的是:公有、私有。
- 公有,在任何地方都可以调用这个成员。
- 私有,只有在类的内部才可以调用改成员(成员是以两个下划线开头,则表示该成员为私有)。
class Foo(object):
def \_\_init\_\_(self, name, age):
self.\_\_name = name
self.age = age
def get\_data(self):
return self.\_\_name
def get\_age(self):
return self.age
obj = Foo("华青水上", 123)
# 公有成员
print(obj.age)
v1 = self.get\_age()
print(v1)
# 私有成员
# print(obj.\_\_name) # 错误,由于是私有成员,只能在类中进行使用。
v2 = obj.get\_data()
print(v2)
**特别提醒:**父类中的私有成员,子类无法继承。
class Base(object):
def \_\_data(self):
print("base.\_\_data")
def num(self):
print("base.num")
class Foo(Base):
def func(self):
self.num()
self.\_\_data() # # 不允许执行父类中的私有方法
obj = Foo()
obj.func()
class Base(object):
def \_\_data(self):
print("base.\_\_data")
def num(self):
print("base.num")
self.\_\_data() # 不允许执行父类中的私有方法
class Foo(Base):
def func(self):
self.num()
obj = Foo()
obj.func()
按理说私有成员是无法被外部调用,但如果用一些特殊的语法也可以(Flask源码中有这种写法,大家写代码不推荐这样写)。
class Foo(object):
def \_\_init\_\_(self):
self.\_\_num = 123
self.age = 19
def \_\_msg(self):
print(1234)
obj = Foo()
print(obj.age)
print(obj.\_Foo\_\_num)
obj.\_Foo\_\_msg()
成员是否可以作为独立的功能暴露给外部,让外部调用并使用。
- 可以,公有。
- 不可以,内部其他放的一个辅助,私有。
三、对象嵌套
在基于面向对象进行编程时,对象之间可以存在各种各样的关系,例如:组合、关联、依赖等(Java中的称呼),用大白话来说就是各种嵌套。
情景一:
class Student(object):
""" 学生类 """
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
def message(self):
data = "我是一名学生,我叫:{},我今年{}岁".format(self.name, self.age)
print(data)
s1 = Student("华青水上", 19)
s2 = Student("殊途同归", 19)
s3 = Student("春花秋月", 19)
class Classes(object):
""" 班级类 """
def \_\_init\_\_(self, title):
self.title = title
self.student\_list = \[\]
def add\_student(self, stu\_object):
self.student\_list.append(stu\_object)
def add\_students(self, stu\_object\_list):
for stu in stu\_object\_list:
self.add\_student(stu)
def show\_members(self):
for item in self.student\_list:
# print(item)
item.message()
c1 = Classes("三年二班")
c1.add\_student(s1)
c1.add\_students(\[s2, s3\])
print(c1.title)
print(c1.student\_list)
情景二:
class Student(object):
""" 学生类 """
def \_\_init\_\_(self, name, age, class\_object):
self.name = name
self.age = age
self.class\_object = class\_object
def message(self):
data = "我是一名{}班的学生,我叫:{},我今年{}岁".format(self.class\_object.title, self.name, self.age)
print(data)
class Classes(object):
""" 班级类 """
def \_\_init\_\_(self, title):
self.title = title
c1 = Classes("Python全栈")
c2 = Classes("Linux云计算")
user\_object\_list = \[
Student("华青水上", 19, c1),
Student("殊途同归", 19, c1),
Student("春花秋月", 19, c2)
\]
for obj in user\_object\_list:
print(obj.name,obj.age, obj.class\_object.title)
情景三:
class Student(object):
""" 学生类 """
def \_\_init\_\_(self, name, age, class\_object):
self.name = name
self.age = age
self.class\_object = class\_object
def message(self):
data = "我是一名{}班的学生,我叫:{},我今年{}岁".format(self.class\_object.title, self.name, self.age)
print(data)
class Classes(object):
""" 班级类 """
def \_\_init\_\_(self, title, school\_object):
self.title = title
self.school\_object = school\_object
class School(object):
""" 学校类 """
def \_\_init\_\_(self, name):
self.name = name
s1 = School("北京校区")
s2 = School("上海校区")
c1 = Classes("Python全栈", s1)
c2 = Classes("Linux云计算", s2)
user\_object\_list = \[
Student("华青水上", 19, c1),
Student("殊途同归", 19, c1),
Student("春花秋月", 19, c2)
\]
for obj in user\_object\_list:
print(obj.name, obj.class\_object.title , obj.class\_object.school\_object.name)
四、特殊成员
在Python的类中存在一些特殊的方法,这些方法都是 __方法__
格式,这种方法在内部均有特殊的含义,接下来我们来讲一些常见的特殊成员:
__init__
,初始化方法
class Foo(object):
def \_\_init\_\_(self, name):
self.name = name
obj = Foo("华青水上")
__new__
,构造方法
class Foo(object):
def \_\_init\_\_(self, name):
print("第二步:初始化对象,在空对象中创建数据")
self.name = name
def \_\_new\_\_(cls, \*args, \*\*kwargs):
print("第一步:先创建空对象并返回")
return object.\_\_new\_\_(cls)
obj = Foo("华青水上")
__call__
class Foo(object):
def \_\_call\_\_(self, \*args, \*\*kwargs):
print("执行call方法")
obj = Foo()
obj()
__str__
class Foo(object):
def \_\_str\_\_(self):
return "哈哈哈哈"
obj = Foo()
data = str(obj)
print(data)
__dict__
class Foo(object):
def \_\_init\_\_(self, name, age):
self.name = name
self.age = age
obj = Foo("华青水上",19)
print(obj.\_\_dict\_\_)
__getitem__
、__setitem__
、__delitem__
class Foo(object):
def \_\_getitem\_\_(self, item):
pass
def \_\_setitem\_\_(self, key, value):
pass
def \_\_delitem\_\_(self, key):
pass
obj = Foo("华青水上", 19)
obj\["x1"\]
obj\['x2'\] = 123
del obj\['x3'\]
__enter__
、__exit__
class Foo(object):
def \_\_enter\_\_(self):
print("进入了")
return 666
def \_\_exit\_\_(self, exc\_type, exc\_val, exc\_tb):
print("出去了")
obj = Foo()
with obj as data:
print(data)
# 面试题(补充代码,实现如下功能)
class Context:
def \_\_enter\_\_(self):
return self
def \_\_exit\_\_(self, exc\_type, exc\_val, exc\_tb):
pass
def do\_something(self): # \_\_enter\_\_返回self才可以调用执行do\_something方法
pass
with Context() as ctx:
ctx.do\_something()
上述面试题属于上下文管理的语法。
__add__
等
class Foo(object):
def \_\_init\_\_(self, name):
self.name = name
def \_\_add\_\_(self, other):
return "{}-{}".format(self.name, other.name)
v1 = Foo("alex")
v2 = Foo("sb")
# 对象+值,内部会去执行 对象.\_\_add\_\_方法,并将+后面的值当做参数传递过去。
v3 = v1 + v2
print(v3)
__iter__
迭代器
\# 迭代器类型的定义:
1.当类中定义了 \_\_iter\_\_ 和 \_\_next\_\_ 两个方法。
2.\_\_iter\_\_ 方法需要返回对象本身,即:self
3. \_\_next\_\_ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。
官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types
# 创建 迭代器类型 :
class IT(object):
def \_\_init\_\_(self):
self.counter = 0
def \_\_iter\_\_(self):
return self
def \_\_next\_\_(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 根据类实例化创建一个迭代器对象:
obj1 = IT()
# v1 = obj1.\_\_next\_\_()
# v2 = obj1.\_\_next\_\_()
# v3 = obj1.\_\_next\_\_() # 抛出异常
v1 = next(obj1) # obj1.\_\_next\_\_()
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = IT()
for item in obj2: # 首先会执行迭代器对象的\_\_iter\_\_方法并获取返回值,一直去反复的执行 next(对象)
print(item)
迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。
for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。
生成器
\# 创建生成器函数
def func():
yield 1
yield 2
# 创建生成器对象(内部是根据生成器类generator创建的对象),生成器类的内部也声明了:\_\_iter\_\_、\_\_next\_\_ 方法。
obj1 = func()
v1 = next(obj1)
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = func()
for item in obj2:
print(item)
如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(生成器也是一个中特殊的迭代器)。
可迭代对象
\# 如果一个类中有\_\_iter\_\_方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。
class Foo(object):
def \_\_iter\_\_(self):
return 迭代器对象(生成器对象)
obj = Foo() # obj是 可迭代对象。
# 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 \_\_iter\_\_ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:
pass
可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
class IT(object):
def \_\_init\_\_(self):
self.counter = 0
def \_\_iter\_\_(self):
return self
def \_\_next\_\_(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
class Foo(object):
def \_\_iter\_\_(self):
return IT()
obj = Foo() # 可迭代对象
for item in obj: # 循环可迭代对象时,内部先执行obj.\_\_iter\_\_并获取迭代器对象;不断地执行迭代器对象的next方法。
print(item)
\# 基于可迭代对象&迭代器实现:自定义range
class IterRange(object):
def \_\_init\_\_(self, num):
self.num = num
self.counter = -1
def \_\_iter\_\_(self):
return self
def \_\_next\_\_(self):
self.counter += 1
if self.counter == self.num:
raise StopIteration()
return self.counter
class Xrange(object):
def \_\_init\_\_(self, max\_num):
self.max\_num = max\_num
def \_\_iter\_\_(self):
return IterRange(self.max\_num)
obj = Xrange(100)
for item in obj:
print(item)
class Foo(object):
def \_\_iter\_\_(self):
yield 1
yield 2
obj = Foo()
for item in obj:
print(item)
\# 基于可迭代对象&生成器 实现:自定义range
class Xrange(object):
def \_\_init\_\_(self, max\_num):
self.max\_num = max\_num
def \_\_iter\_\_(self):
counter = 0
while counter < self.max\_num:
yield counter
counter += 1
obj = Xrange(100)
for item in obj:
print(item)
常见的数据类型:
from collections.abc import Iterator, Iterable
v1 = \[11, 22, 33\]
print( isinstance(v1, Iterator) ) # false,判断是否是迭代器;判断依据是\_\_iter\_\_ 和 \_\_next\_\_。
v2 = v1.\_\_iter\_\_()
print( isinstance(v2, Iterator) ) # True
v1 = \[11, 22, 33\]
print( isinstance(v1, Iterable) ) # True,判断依据是是否有 \_\_iter\_\_且返回迭代器对象。
v2 = v1.\_\_iter\_\_()
print( isinstance(v2, Iterable) ) # True,判断依据是是否有 \_\_iter\_\_且返回迭代器对象。
至此,Python进阶面向对象之成员总结完毕,如有不当之处欢迎指正。
关于Python技术储备
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!
保存图片微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
一、Python所有方向的学习路线
Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
二、Python基础学习视频
② 路线对应学习视频
还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~在这里插入图片描述
③练习题
每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
因篇幅有限,仅展示部分资料
三、精品Python学习书籍
当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。
四、Python工具包+项目源码合集
①Python工具包
学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
②Python实战案例
光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
③Python小游戏源码
如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
五、面试资料
我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
六、Python兼职渠道
而且学会Python以后,还可以在各大兼职平台接单赚钱,各种兼职渠道+兼职注意事项+如何和客户沟通,我都整理成文档了。
这份完整版的Python全套学习资料已经上传CSDN,朋友们如果需要可以保存图片微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】