Python面向对象之成员相关知识总结


Posted in Python onJune 24, 2021

1、成员

 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)

2.成员修饰符

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()

成员是否可以作为独立的功能暴露给外部,让外部调用并使用。

  • 可以,公有。
  • 不可以,内部其他放的一个辅助,私有。

3.对象嵌套

在基于面向对象进行编程时,对象之间可以存在各种各样的关系,例如:组合、关联、依赖等(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)

4.特殊成员

在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获取DLL和EXE文件版本号的方法
Mar 10 Python
收藏整理的一些Python常用方法和技巧
May 18 Python
Django实现图片文字同时提交的方法
May 26 Python
遗传算法之Python实现代码
Oct 10 Python
Python中Scrapy爬虫图片处理详解
Nov 29 Python
Python实现拷贝/删除文件夹的方法详解
Aug 29 Python
python文件转为exe文件的方法及用法详解
Jul 08 Python
python字典嵌套字典的情况下找到某个key的value详解
Jul 10 Python
Django 查询数据库并返回页面的例子
Aug 12 Python
Ubuntu16.04安装python3.6.5步骤详解
Jan 10 Python
运行python提示no module named sklearn的解决方法
Nov 29 Python
python全面解析接口返回数据
Feb 12 Python
Python面向对象之内置函数相关知识总结
Jun 24 #Python
python面向对象版学生信息管理系统
Python实现学生管理系统(面向对象版)
Jun 24 #Python
Pycharm连接远程服务器并远程调试的全过程
Python函数中的不定长参数相关知识总结
Jun 24 #Python
Django REST framework 限流功能的使用
Jun 24 #Python
Python 发送SMTP邮件的简单教程
You might like
二十行语句实现从Excel到mysql的转化
2006/10/09 PHP
thinkPHP模板中for循环与switch语句用法示例
2016/11/30 PHP
php安装dblib扩展,连接mssql的具体步骤
2017/03/02 PHP
PHP下载文件函数与用法示例
2019/09/27 PHP
jquery png 透明解决方案(推荐)
2010/08/21 Javascript
jquery异步循环获取功能实现代码
2010/09/19 Javascript
jquery三个关闭弹出层的小示例
2013/11/05 Javascript
jQuery实现首页图片淡入淡出效果的方法
2015/06/10 Javascript
jQuery添加删除DOM元素方法详解
2016/01/18 Javascript
JS获取复选框的值,并传递到后台的实现方法
2016/05/30 Javascript
js仿微博动态栏功能
2017/02/22 Javascript
jQuery实现的form转json经典示例
2017/10/10 jQuery
javascript将json格式数组下载为excel表格的方法
2017/12/22 Javascript
Vue filter介绍及详细使用
2018/04/04 Javascript
详解React Native 屏幕适配(炒鸡简单的方法)
2018/06/11 Javascript
小程序开发基础之view视图容器
2018/08/21 Javascript
jQuery实现图片下载代码
2019/07/18 jQuery
JS实现字体背景跑马灯
2020/01/06 Javascript
微信小程序swiper实现文字纵向轮播提示效果
2020/01/21 Javascript
如何实现echarts markline标签名显示自己想要的
2020/07/20 Javascript
[01:08:10]2014 DOTA2国际邀请赛中国区预选赛 SPD-GAMING VS LGD-CDEC
2014/05/22 DOTA
Python中使用Beautiful Soup库的超详细教程
2015/04/30 Python
Python使用add_subplot与subplot画子图操作示例
2018/06/01 Python
Pycharm无法显示动态图片的解决方法
2018/10/28 Python
Django框架用户注销功能实现方法分析
2019/05/28 Python
Python的信号库Blinker用法详解
2020/12/31 Python
金牌葡萄酒俱乐部:Gold Medal Wine Club
2017/11/02 全球购物
村级换届选举方案
2014/05/10 职场文书
党员民主生活会对照检查材料思想汇报
2014/09/28 职场文书
房产销售独家委托书范本
2014/10/01 职场文书
雨雪天气温馨提示
2015/07/15 职场文书
大学体育课感想
2015/08/10 职场文书
《火烧云》教学反思
2016/02/23 职场文书
幼儿园六一儿童节开幕词
2016/03/04 职场文书
教你做个可爱的css滑动导航条
2021/06/15 HTML / CSS
mysq启动失败问题及场景分析
2021/07/15 MySQL