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 ValueError: invalid literal for int() with base 10 实用解决方法
Jun 21 Python
Python yield 使用方法浅析
May 20 Python
Python复数属性和方法运算操作示例
Jul 21 Python
python多进程实现文件下载传输功能
Jul 28 Python
Django Rest framework之认证的实现代码
Dec 17 Python
Python面向对象程序设计构造函数和析构函数用法分析
Apr 12 Python
Django的性能优化实现解析
Jul 30 Python
关于Python-faker的函数效果一览
Nov 28 Python
Python+OpenCV+图片旋转并用原底色填充新四角的例子
Dec 12 Python
python getopt模块使用实例解析
Dec 18 Python
使用Python串口实时显示数据并绘图的例子
Dec 26 Python
Pytorch十九种损失函数的使用详解
Apr 29 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
php 生成WML页面方法详解
2009/08/09 PHP
Thinkphp中的volist标签用法简介
2014/06/18 PHP
PHP命令行脚本接收传入参数的三种方式
2014/08/20 PHP
PHP实现批量生成App各种尺寸Logo
2015/03/19 PHP
php冒泡排序与快速排序实例详解
2015/12/07 PHP
PHP将二维数组某一个字段相同的数组合并起来的方法
2016/02/26 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
2017/07/19 PHP
docker-compose部署php项目实例详解
2019/07/30 PHP
Aster vs KG BO3 第二场2.19
2021/03/10 DOTA
JavaScript 函数调用规则
2009/09/14 Javascript
JavaScript加入收藏夹功能(兼容IE、firefox、chrome)
2014/05/05 Javascript
Jquery倒计时源码分享
2014/05/16 Javascript
纯js模拟div层弹性运动的方法
2015/07/27 Javascript
莱鸟介绍window.print()方法
2016/01/06 Javascript
jQuery实现多级联动下拉列表查询框
2016/01/18 Javascript
JavaScript兼容性总结之获取非行间样式案例
2016/08/07 Javascript
JavaScript中定义对象原型的两种使用方法
2016/12/15 Javascript
解决ztree搜索中多级菜单展示不全问题
2017/07/05 Javascript
JS调用安卓手机摄像头扫描二维码
2018/10/16 Javascript
原生JS使用Canvas实现拖拽式绘图功能
2019/06/05 Javascript
js图片查看器插件用法示例
2019/06/22 Javascript
中级前端工程师必须要掌握的27个JavaScript 技巧(干货总结)
2019/09/23 Javascript
[02:37]2018DOTA2亚洲邀请赛赛前采访-EG篇
2018/04/03 DOTA
python基于Tkinter库实现简单文本编辑器实例
2015/05/05 Python
python之PyMongo使用总结
2017/05/26 Python
Python实现时钟显示效果思路详解
2018/04/11 Python
Python修改文件往指定行插入内容的实例
2019/01/30 Python
贝玲妃美国官方网站:Benefit美国
2016/08/28 全球购物
波比布朗英国官网:Bobbi Brown英国
2017/11/13 全球购物
国外的一些J2EE面试题一
2012/10/13 面试题
毕业生自荐信的主要内容
2013/10/29 职场文书
婚礼证婚人证婚词
2014/01/08 职场文书
医院反腐倡廉演讲稿
2014/09/16 职场文书
四风问题自查自纠工作情况报告
2014/10/28 职场文书
会计岗位职责
2015/02/03 职场文书
2016七夕情人节感言
2015/12/09 职场文书