首页 > 编程语言 >python基础-面向对象2

python基础-面向对象2

时间:2023-10-20 16:55:38浏览次数:28  
标签:__ obj name python self 基础 面向对象 print def

目录

1. 成员

面向对象中的所有成员如下:

  • 变量
    • 实例变量
    • 类变量
  • 方法
    • 绑定方法
    • 类方法
    • 静态方法
  • 属性

1.1 变量

  • 实例变量,属于对象,每个对象中各自维护自己的数据
  • 类变量,属于类,可以被所有对象共享,一般用于给对象提供公共数据(类似于全局变量)

当每个对象中都存在的相同的实例变量时,可以选择把它放在类变量中,这样就可以避免对象中维护多个相同数据

  • 写变量需注意是类变量还是实例变量
  • 读类变量在类中读,读实例变量优先在实例对象中读,没有再去类中读
class Person(object):
    country = "中国"
    country2 = "俄罗斯"
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def show(self):
        msg = "{}-{}-{}".format(self.country,self.name,self.age)
        print(msg)

print(Person.country)       # 中国 类变量
Person.country = "CHINA"    # 在类中将类变量country重置为 CHINA
print(Person.country)       # CHINA

p1 = Person('小明','18')
print(p1.name,p1.age)       # 小明 18
p1.show()                   # 中国-小明-18
p1.name = 'root'            # 在对象p1中将实例变量name重置为 root
p1.num = 19                 # 在对象p1中新增实例变量 num = 19
p1.country = 'china'        # 在对象p1中新增实例变量 conutry = china
print(p1.country)           # china 优先在自己实例变量中找
print(p1.country2)          # 俄罗斯 优先在自己实例变量中找,没有再去类变量中找
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)      # 中国  优先在自己的类中找,没有再去继承的Base类中去找

obj = Person("小明",19)
print(obj.country)         # 中国  优先在自己的类中找,没有再去继承的Base类中去找

# 写变量
Base.country = "china"     # 修改Base类变量中 country的值
Person.country = "泰国"     # 创建Person类变量 country = "泰国"
obj.country = "日本"        # 赋值obj对象实例变量 country = "日本"
# 面试题

class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)

Child1.x = 2
print(Parent.x, Child1.x, Child2.x)

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

1.2 方法

在Python中比较灵活,方法可以通过对象和类进行调用;而在java、c#等语言中,绑定方法只能由对象调用;类方法或静态方法只能由类调用

类方法 分为两大类三小类
三小类: 类方法、实例方法、静态方法
两大类:

  • 绑定方法:
    • 实例方法(self):绑定给实例去使用的方法,默认有一个self参数,由对象进行调用,调用的时候会默认传入self(此时self就等于调用方法的这个对象)【只有对象可调用】
    • 类方法(classmethod): 绑定给类去使用的方法,默认有一个cls参数,类去调用时,会默认把类本身和参数一起传给类方法 【对象&类均可调用】
  • 非绑定方法:
    • 静态方法(@staticmethod): 既没绑定给类也没绑定给实例,相当于一个普通的函数,无默认参数【对象&类均可调用】
class Foo(object):
    cls = "Foo"   # 类属性

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def f1(self):
        print("绑定方法", self.name)

    @classmethod
    def f2(cls):        # 类方法的触发者是类,当类在触发的时候,把自己当作参数传给cls = class
        print(cls.cls)  # 打印类属性

    @staticmethod
    def f3():
        print("静态方法")


# 实例方法(对象)
obj = Foo("小明", 20)
obj.f1()  # Foo.f1(obj)

# 类方法
Foo.f2()  # cls就是当前调用这个方法的类
obj.f2()  # cls就是当前调用这个方法的对象的类。

# 静态方法
Foo.f3()  # 类执行方法(类)
obj.f3()  # 对象执行方法

在类中 @classmethod@staticmethod 的作用?

  • 在类中用什么方法取决于你方法中用的什么变量
    • 用到self了就用实例方法
    • 用到cls了就用类方法
    • 什么都没用到就用staticmethod

1.3 属性

在python中属性的使用少,但是在其他的语言中属性用的非常多,因为在python中属性是后来才有的,他的功能目前还不是很强大!
但是他要告诉人们我也是支持属性的,所以才有了这个属性!
属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。
属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象

属性:由实例方法 + 特殊装饰器 组合创造出来的

class Pager:
    def __init__(self,current_page):
        # 用户当前请求的页码(第一页、第二页...)
        self.current_page = current_page
        # 每页默认显示10条数据
        self.per_items = 10

    @property
    def start(self):
        val = ((self.current_page - 1) * self.per_items) + 1
        return val
    @property
    def end(self):
        var = self.current_page * self.per_items
        return var

p = Pager(5)
print(p.start) # 41
print(p.end)   # 50
class DataSet(object):
    def __init__(self):
        self._images = 1
        self._labels = 2 #定义属性的名称
    @property
    def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。
        return self._images 
    @property
    def labels(self):
        return self._labels
l = DataSet()
# 用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。
  • @property装饰器作用:

    • 将python定义的函数"当做"属性访问
    • 对要读取的数据进行预处理
    • 只有@property表示只读
  • property的构造方法中有四个参数

    • 第一个参数是方法名,调用对象.属性时自动触发执行方法
    • 第二个参数是方法名,调用对象.属性 = XXX时自动触发执行方法
    • 第三个参数是方法名,调用del 对象.属性时自动触发执行方法
    • 第二个参数是字符串,调用对象.属性.__doc__,此参数是该属性的描述信息
  • @*.setter装饰器作用:

    • 设置可写属性(不可修改)
    • 对要存入的数据进行预处理
    • @*.setter装饰器必须在@property的后面,且两个被修饰的函数名称必须保持一致
    • 同时有@property和@*.setter表示可读可写
  • @*.deleter装饰器作用:

    • 定义可读可写可删除属性
    • 同时有@property和@.setter和@.deleter表示可读可写可删除
class result:
    def __init__(self):
        self.__data = [11, 33, 44, 55, 66]
        self.__pass_score = 60

        @property
        def data(self):
            return self.__data

        @property
        def total(self):
            total_ = 0
            for value in self.__data:
                total_ += value
                return total_

            @property
            def passCount(self):
                count = 0
                for value in self.__data:
                    if value >= self.__pass_score:
                        count += 1
                        return count

            @property
            def passScore(self):
                return self.__pass_score

            @passScore.setter
            def passScore(self, value):
                if not 0 < value < 100:
                    raise ValueError('必须为1~99的数')
                self.__pass_score = value

属性的编写有两种方式:

  • 方式一,基于装饰器
class Foo(object):
    @property
    def f1(self):
        return self.name

    @f1.setter
    def f1(self,name):
        if name == "小明":
            self.name = name
        else:
            self.name = "other"

    @f1.deleter
    def f1(self):
        del self.f1

obj = Foo()

obj.f1 = '小王'
print(obj.f1)  # @f1.setter判断不是"小明",将实例变量name设为传入的属性

del obj.name   # 删除属性
print(obj.f1)  # 报错

  • 方式二,基于定义变量
class Foo(object):

    def getx(self):
        return self.name

    def setx(self, name):
        if name == "小明":
            self.name = name
        else:
            self.name = "other"

    def delx(self):
        del self.name

    x = property(getx, setx, delx, "这是注释")


obj = Foo()

obj.x = "小明"
print(obj.x)

del obj.name
print(obj.x)

由于属性和实例变量的调用方式相同,所以在编写时需要注意:属性名称 不要和 实例变量 重名,一旦重名,可能就会有报错

  • 如果真的想要在名称上创建一些关系,可以让实例变量加上一个下划线
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中成员的修饰符就是指的是:公有、私有。

  • 公有:在任何地方都可以调用该成员。
  • 私有:只有在类的内部才可以调用该成员(成员是以两个下划线开头,则表示该成员为私有)

父类中的私有成员,子类无法继承

示例1:私有实例变量

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)
print(Foo("小明", 123).get_age())

# 私有成员
# print(obj.__name) # 错误,由于是私有成员,只能在类中进行使用
print(Foo("小明", 123).get_data())  # 可通过公用的实例方法调用内部私有变量

示例2:私有方法

class Foo(object):

    def get_age(self):
        print("公有的get_age")

    def __get_data(self):
        print("私有的__get_data方法")

    def proxy(self):
        print("公有的proxy")
        self.__get_data()


obj = Foo()
obj.get_age()
obj.proxy()

示例3:私有属性

class Foo(object):

    @property
    def __name(self):
        print("私有的属性")

    @property
    def proxy(self):
        print("公有的属性")
        self.__name
        return 1


obj = Foo()
print(obj.proxy)  # 在类内部的公有属性中调用私有属性

按理说私有成员是无法被外部调用,但如果用一些特殊的语法也可以(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. 对象嵌套

情景一:

class Student(object):
    """学生类"""

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def msg(self):
        print("学生姓名: {},年龄: {}".format(self.name, self.age))


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.student_list.append(stu)

    def show_members(self):
        for item in self.student_list:
            item.msg()
            # print(item.name,item.age)


s1, s2, s3 = Student("小明", 18), Student("小红", 17), Student("小王", 30)
c1 = Classes("二年二班")
c1.add_student(s1)
c1.add_students([s2, s3])
c1.show_members()

情景二:

class Student(object):
    """学生类"""

    def __init__(self, name, age, class_object):
        self.name = name
        self.age = age
        self.class_object = class_object

    def msg(self):
        print("学生姓名: {},年龄: {},班级: {}".format(self.name, self.age, self.class_object.title))


class Classes(object):
    """班级类"""

    def __init__(self, title):
        self.title = title


c1 = Classes("二年二班")
c2 = Classes("二年三班")

user_object_list = [
    Student('小明', 18, c1),
    Student('小红', 17, c1),
    Student('小花', 16, c2)
]

for stu in user_object_list:
    # print(stu.name,stu.age,stu.class_object.title)
    stu.msg()

情景三:

class Student(object):
    """学生类"""

    def __init__(self, name, age, class_object):
        self.name = name
        self.age = age
        self.class_object = class_object

    def msg(self):
        print("学生姓名: {},年龄: {},班级: {},校区: {}".format(self.name, self.age, self.class_object.title,
                                                     self.class_object.school_object.name))


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


sc1 = School("北京")
sc2 = School("广州")

c1 = Classes("二年二班", sc1)
c2 = Classes("二年三班", sc2)

user_object_list = [
    Student('小明', 18, c1),
    Student('小红', 17, c1),
    Student('小花', 16, c2)
]

for stu in user_object_list:
    # print(stu.name,stu.age,stu.class_object.title,stu.class_object.school_object.name)
    stu.msg()

4. 特殊方法

在Python的类中存在一些特殊的方法,这些方法都是 __方法__ 格式,这种方法在内部均有特殊的含义

  1. __init__  初始化方法,在实例化对象的时候自动执行
class Foo(object):
    def __init__(self, name):
        self.name = name


obj = Foo("小明")
  1. __new__ 构造方法,在init方法触发前触发 平时使用会忽略此方法,自动去父类object中执行__new__方法创建空对象,可以重写此方法创造单例模式

    作用:

  2. 为创建的对象分配内存

  3. 返回对象的引用

class Foo(object):
    def __new__(cls, *args, **kwargs):
        print("第一步:先创建空对象并返回")
        return object.__new__(cls)

    def __init__(self, name):
        print("第二步:初始化对象,在空对象中创建数据")
        self.name = name


obj = Foo("小明")



# 单例模式
class MusicPlayer(object):
    # 记录第一个被创建对象的引用
    instance = None
    # 记录是否执行过初始化方法
    init_flag = False

    def __new__(cls, *args, **kwargs):
        # 判断类属性是否是空对象
        if not cls.instance:
            # 调用父类的new方法,为第一个对象分配空间
            cls.instance = super().__new__(cls)
            # cls.instance = object.__new__(cls)
        # 返回类属性保存的对象引用
        return cls.instance

    def __init__(self):
        # 判断是否执行过初始化方法
        if MusicPlayer.init_flag:
            return
        # 未执行过,执行
        print('初始化播放器')
        # 修改类属性的标记
        MusicPlayer.init_flag = True


player1 = MusicPlayer()
player2 = MusicPlayer()
print(player1, player2)
  1. __call__  类创建完对象后,在执行对象时加(),则执行call方法
class Foo(object):

    def __call__(self, *args, **kwargs):
        print("执行__call__方法")


obj = Foo()
obj()  # 对象执行call方法
  1. __str__ 把对象转换成字符串,打印对象时,将返回str方法的返回值, 会自动转换
class Foo(object):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name


obj = Foo(name='小明')
print(obj)  # 小明
  1. __dict__  将实例变量转换成字典的形式
class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = 18


obj = Foo(name='小明', age='18')
print(obj.__dict__)  # {'name': '小明', 'age': 18}
class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = 18

    @property
    def return_dict(self):
        return self.__dict__


obj = Foo(name='小明', age='18')
print(obj.return_dict)  # {'name': '小明', 'age': 18}
  1. __getitem____setitem____delitem__, 像字典那样设置值,取值,删除值
  • 参考字典操作的方式理解
    • __getitem__(self,key): 返回键对应的值。
    • __setitem__(self,key,value): 设置给定键的值
    • __delitem__(self,key): 删除给定键对应的元素。
    • __len__(): 返回元素的数量
  • 这些魔术方法的原理就是:当我们对类的属性item进行下标的操作时,首先会被getitem()setitem()delitem()len()拦截,从而进行我们在方法中设定的操作,如赋值,修改内容,删除内容等等
class Foo(object):
    def __init__(self):
        self.mydict = {}

    def __setitem__(self, key, value):
        self.mydict[key] = value
        print("设置:{} = {}".format(key, value))

    def __getitem__(self, item):
        print("获取 键{} 对应的值为:{}".format(item, self.mydict[item]))

    def __delitem__(self, key):
        print("删除键:{}".format(self.mydict[key]))
        del self.mydict[key]

    def __len__(self):  # __len__必须设置return返回值
        print("获取mydict长度为: {}".format(len(self.mydict)))
        return (len(self.mydict))


obj = Foo()
# 自动触发类中的 __setitem__
obj["name"] = "小明"  # 设置:name = 小明
# 自动触发类中的 __setitem__
obj["age"] = 18  # 设置:age = 18
# 自动触发类中的 __getitem__
obj["name"]  # 获取 键name 对应的值为:小明  
# 自动触发类中的 __delitem__
del obj['name']  # 删除键:小明 
# 自动触发类中的 __len__
len(obj)  # 获取mydict长度为: 1
  1. __enter____exit__ 一般都是成对出现,使对象支持上下文管理 (参考上下文管理理解)
class Foo(object):
    def __init__(self):
        self.conn = "数据库连接"

    def __enter__(self):
        print(self.conn, '进来了')
        return self.conn

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(self.conn, '关闭', '出去了')


obj = Foo()
with obj as f:  # with 对象 as f1,在内部会执行__enter__方法
    print(123)  # 123
    print(f)  # 对应__enter__方法内的return
# 当with缩进中的代码块执行完毕,字典会执行__exit__  "print("出去了")"

应用场景: 连接数据库

  • 每次对远程的数据进行操作时候都必须经历
      1. 连接 = 连接数据库
      1. 操作数据库
    • 3.关闭连接
class SqlHelper(object):
    def __init__(self):
        self.连接 = 连接数据库
        self.游标 = 创建游标
    def __enter__(self):
        return 连接
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.游标.关闭
        self.连接.关闭
    def exec_sql(self,sql):
        self.cursor.execute(sql)
        self.conn.commit()
        result = self.cursor.fetchall()
        return result
        
     
with SqlHelper() as 连接:
    连接.操作...
    

"""
import pymysql


class ConnMysql(object):
    def __init__(self):
        self.conn = conn = pymysql.connect(host='192.168.1.20', port=3306, user='root', password='abc123',
                                           charset='utf8')
        self.cursor = conn.cursor()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.cursor.close()
        self.conn.close()

    # 操作数据库
    def execute_sql(self, sql):
        self.cursor.execute(sql)
        self.conn.commit()
        result = self.cursor.fetchall()
        print(result)


obj = ConnMysql()
with ConnMysql() as obj:
    obj.execute_sql('show databases')
    obj.execute_sql('use day26db')
    obj.execute_sql('show tables')
"""
  1. __add__ :相当于求和运算,可以使两个对象可以相加
class Foo(object):
    def __init__(self, name):
        self.name = name

    def __add__(self, other): # other代表另一个class
        return "{}-{}".format(self.name, other.name)


v1 = Foo("a")
v2 = Foo("b")
# 对象+值,内部会去执行 对象.__add__方法,并将+后面的值当做参数传递过去
v3 = v1 + v2  # other是v2对象
print(v3)  # a-b
class Foo(object):
    def __init__(self):
        self.x = 10

obj = Foo()
print(obj.x.__add__(6)) # 16
  1. __iter__
    image-20220411215323207.png
  • 迭代器
# 迭代器类型的定义:
   # 1.当类中定义了 __iter__ 和 __next__ 两个方法。
   # 2.__iter__ 方法需要返回对象本身,即:self
   # 3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。
   # 官方文档:https://docs.python.org/3/library/stdtypes.html#iterator-types

# 创建迭代器类型        
class Iter():
    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

# 根据类型示例化创建一个迭代器对象
obj = Iter()

"""
v1 = obj.__next__() # 1
v2 = obj.__next__() # 2
v3 = obj.__next__() # 抛出异常
"""

"""
v1 = next(obj) # 1
v2 = next(obj) # 2
v3 = next(obj) # 抛出异常
"""

for item in obj: # 首先会执行迭代器对象的__iter__方法并获取返回值,一直反复去执行__next__(对象)
    print(item)
    
# 迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration
# for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值 (有异常StopIteration则终止循环)
  • 生成器
    • 如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类(生成器是一种特殊的迭代器)
# 创建生成器函数
def func():
    yield 1
    yield 2


# 创建生成器对象(内部是根据生成器类generator创建的对象)
obj = func()

# 生成器类的内部也声明了:__iter__、__next__ 方法
print(dir(obj))

"""
v1 = next(obj) # 1
v2 = next(obj) # 2
v3 = next(obj) # 抛异常
"""

for item in obj:
    print(item)
  • 可迭代对象
# 如果一个类中有__iter__方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。

class Foo(object):
    
    def __iter__(self):
        return 迭代器对象(生成器对象)
    
obj = Foo() # obj是 可迭代对象。

# 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:
    pass
# 迭代器类
class Iterator(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 Iterable(object):
    def __iter__(self):
        return Iterator()


# 可迭代对象
obj = Iterable()
# 可迭代对象中只有__iter__方法
print(dir(obj))
# 执行可迭代对象中的__iter__方法,返回迭代器对象,迭代器对象包含__iter__和__next__

print(dir(obj.__iter__()))
for item in obj:  # 循环可迭代对象时,内部会先执行obj.__iter__方法获取迭代器对象
    print(item)  # 不断执行迭代器对象的__next__方法,直到 raise StopIteration()
# 基于迭代器和可迭代对象实现一个自定义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)

# 基于迭代器和可迭代对象实现一个自定义range

class IterRange(object):
    def __init__(self, num):
        self.num = num
        self.counter = -1

    def __iter__(self):
        while self.counter < self.num:
            yield self.counter
            self.counter += 1


obj = IterRange(100)
# print(dir(obj.__iter__()))
for item in obj:
    print(item)

5. 练习题

  1. @staticmethod@classmethod的作用
@staticmethod,将一个方法变换为静态方法,静态方法调用的可以是 类也可以是对象,无默认参数
@classmethod,将一个方法变换为类方法,类和方法都可以调用,且cls默认是当前执行该方法的类
  1. 面向对象如何让成员变为私有
前面加上__
  1. __new__方法的作用
__new__是构造方法,用于创建对象(空对象),在__init__方法执行之前
  1. 简述迭代器、生成器、可迭代对象
迭代器: 含有__iter__方法和__next__方法,__iter__返回自身,__next__可以获取数据,没有数据时抛出StopIteration异常,可以被for循环
    
生成器: 在定义函数时包含yield就是生成器函数,执行函数获得生成器对象(一种特殊的迭代器),可以通过next取值,可以被for循环
    
可迭代对象: 含有__iter__方法,且返回一个迭代器对象,可以被for循环
  1. 看代码写结果
class Foo(object):
    a1 = 1

    def __init__(self, num):
        self.num = num


obj1 = Foo(666)
print(obj1.num, obj1.a1)  # 666 1
obj1.num = 18
obj1.a1 = 99  # 注意这里是给对象赋值 a1 = 99 (self.a1 = 99)
print(Foo.a1, obj1.a1)  # 1 99
print(obj1.num, obj1.a1)  # 18 99

obj2 = Foo(999)
print(obj2.num, obj2.a1)  # 999 1
  1. 看代码写结果,注意返回值
class Foo(object):
    @staticmethod
    def f1():
        return 999

    def f2(self):
        v = self.f1()
        print('f2')
        return v

    def f3(self):
        print('f3')
        return self.f2()

    def run(self):
        result = self.f3()
        print(result)


obj = Foo()
v1 = obj.run()
print(v1)
  1. 看代码写结果
class Foo(object):
    def f1(self):
        print('f1')

    @staticmethod
    def f2():
        print('f2')


obj = Foo()
obj.f1()  # print('f1')
obj.f2()  # print('f2')

# Foo.f1()  # 报错 类直接调用绑定方法需要指定self
Foo.f1(Foo)  # f1  类直接调用绑定方法需要指定cls
Foo.f2()  # print('f2')  静态方法不需要参数,通过类和对象都可以调用
  1. 看代码写结果
class Foo(object):
    def f1(self):
        print('f1')
        self.f2()
        self.f3()

    @classmethod
    def f2(cls):
        print('f2')

    @staticmethod
    def f3():
        print('f3')


obj = Foo()
obj.f1()
  1. 看代码写结果
class Base(object):
    @classmethod
    def f2(cls):
        print('f2')

    @staticmethod
    def f3():
        print('f3')


class Foo(Base):
    def f1(self):
        print('f1')
        self.f2()
        self.f3()


obj = Foo()
obj.f1()
  1. 看代码写结果
class Foo(object):
    a1 = 1
    __a2 = 2

    def __init__(self, num):
        self.num = num
        self.__salary = 1000

    def show_data(self):
        print(self.num + self.__a2 + self.__salary)


obj = Foo(666)
print(obj.num, obj.a1)  # 666 1
# print(obj.__salary)   # 私有实例变量,只能在内部调用 报错
# print(obj.__a2)       # 私有类变量,只能在内部调用   报错
print(Foo.a1)  # 1
# print(Foo.__a2)       # 私有的类变量,只能在内部调用 报错
obj.show_data()  # 1668
  1. 看代码写结果
class Foo(object):
    def __init__(self, age):
        self.age = age

    def display(self):
        print(self.age)


data_list = [Foo(8), Foo(9)]  # 实例化两个对象放到列表中做元素
for item in data_list:
    print(item.age, item.display())
  1. 看代码写结果
class Base(object):
    def __init__(self, a1):
        self.a1 = a1

    def f2(self, arg):
        print(self.a1, arg)


class Foo(Base):
    def f2(self, arg):
        print(self.a1, arg)


obj_list = [Base(1), Foo(2), Foo(3)]
obj_list[0].a1  # 1
obj_list[0].f2(123)  # 1 123
obj_list[1].f2(123)  # 2 123
for item in obj_list:
    item.f2(1)
  1. 看代码写结果
class Foo(object):
    def __init__(self, num):
        self.num = num


v1 = [Foo for i in range(10)]  # [ Foo,Foo,Foo... ] 10个类名
v2 = [Foo(5) for i in range(10)]  # [ Foo(5),Foo(5),Foo(5)... ] 10个实例化对象
v3 = [Foo(i) for i in range(10)]  # [ Foo(1),Foo(2),Foo(3)... ] 10个实例化对象

print(v3[9].num)
  1. 看代码写结果
class StarkConfig(object):
    def __init__(self,num):
        self.num = num
    def changelist(self,request):
        print(self.num,request)
        
        
obj_list = [ StarkConfig(1),StarkConfig(2),StarkConfig(3) ]
for item in obj_list:
    item.changelist(666)
  1. 看代码写结果
class StarkConfig(object):
    def __init__(self, num):
        self.num = num

    def changelist(self, request):
        print(self.num, request)

    def run(self):
        self.changelist(999)


class RoleConfig(StarkConfig):
    def changelist(self, request):
        print(666, self.num)


class AdminSite(object):
    def __init__(self):
        self._registry = {}

    def registry(self, k, v):
        self._registry[k] = v


site = AdminSite()  # 实例化了对象

site.registry('root', StarkConfig(10))  # 执行了对象的registry方法 --> k='root',v=StarkConfig(10)对象 (num=10)
site.registry('look', StarkConfig(20))  # 执行了对象的registry方法 --> k='look',v=StarkConfig(20)对象 (num=20)
site.registry('guest', RoleConfig(30))  # 执行了对象的registry方法 --> k='guest',v=RoleConfig(30)对象 找父类的__init__方法 (num=30)

print(len(site._registry))  # 3

for k, row in site._registry.items():
    row.changelist(5)
  1. 看代码写结果
class StarkConfig(object):
    def __init__(self,num):
        self.num = num
    def run(self):
        self()
    def __call__(self,*args,**kwargs):
        print(self.num)

class RoleConfig(StarkConfig):
    def __call__(self,*args,**kwargs):
        print(123)
    def __getitem__(self, item):
        return self.num[item]

    
v1 = RoleConfig('root')
v1()  # 123
print(v1[1]) # o

v2 = StarkConfig('look')
v2()  # look
print(v2[1]) # 报错 StarkConfig类中没有__getitem__方法
  1. 补全代码
class Context:
    pass

with Context() as ctx:
    ctx.do_something()
    
"""
class Context:
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass
    def do_something(self):
        print('xxxx')

with Context() as ctx:
    ctx.do_something()
"""
  1. 看代码写结果
class Department(object):
    def __init__(self,title):
        self.title = title

class Person(object):
    def __init__(self,name,age,depart):
        self.name = name
        self.age = age
        self.depart = depart
    def message(self):
        msg = "姓名:{} 年龄:{} 部门:{}".format(self.name,self.age,self.depart.title)
        print(msg)

d1 = Department('人事部')
d2 = Department('技术部')

p1 = Person('小红',18,d1)
p1.message()

p2 = Person('小王',20,d2)
p2.message()
  1. 看代码写结果
class Node(object):
    def __init__(self,title):
        self.title = title
        self.children = []
    def add(self,node):
        self.children.append(node)
    def __getitem__(self, item):
        return self.children[item]

root = Node('中国')       # (title='中国',children=[Node对象,Node对象])
root.add(Node('广东省'))       
root.add(Node('广西省'))      

print(root.title)    	  # 中国
print(root[0])       	  # Node('广东省') 这个对象 (title='广东省',children=[])
print(root[0].title) 	  # 广东省
  1. 分析代码关系,写结果
    b6ea4ec27b3f158aeefd1d1869aa3a6.png
class Node(object):
    def __init__(self,title):
        self.title = title
        self.children = []
    def add(self,node):
        self.children.append(node)
    def __getitem__(self, item):
        return self.children[item]

root = Node('中国')
root.add(Node('广东省'))
root.add(Node('山东省'))
root.add(Node('河北省'))

root[0].add(Node("广州"))
root[0].add(Node("深圳"))
root[0].add(Node("佛山"))
root[1].add(Node("青岛"))
root[1].add(Node("烟台"))
root[1].add(Node("日照"))
root[2].add(Node("石家庄"))
root[2].add(Node("保定"))
root[2][1].add(Node("雄安"))
root[2][1].add(Node("望都"))

print(root.title)    	      # 中国
print(root[0])       	      # Node('广东省') 这个对象 (title='广东省',children=[Node对象,Node对象,Node对象])
print(root[0].title) 	      # 广东省
print(root[1].title)          # 山东省
print((root[2][0].title))     # 石家庄
print((root[2][1].title))     # 保定
print((root[2][1][0].title))  # 雄安

标签:__,obj,name,python,self,基础,面向对象,print,def
From: https://www.cnblogs.com/ican97/p/17777482.html

相关文章

  • python基础-数据类型(字符串-布尔-整数)
    目录1.整数(int)1.1定义1.2独有功能1.3公共功能1.4转换1.5其他1.5.1长整型1.5.2地板除1.5.3其它2.布尔(bool)2.1定义2.2独有功能2.3公共功能2.4转换2.5其他做条件自动转换3.字符串(str)3.1定义3.2独有功能3.2.1练习题3.3公共功能3.4转换3.5其他4.练习题......
  • 实验2— C语言分支与循环基础应用编程
    1.实验任务1源代码1#include<stdio.h>2#include<stdlib.h>3#include<time.h>45#defineN56#defineN13747#defineN246589intmain()10{11intnumber;12inti;1314srand(time(0));1516for......
  • python异常处理else和finally的区别
    Python3错误和异常|菜鸟教程(runoob.com)try/except...elsetry/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的except子句之后。else子句将在try子句没有发生任何异常的时候执行。以下实例在try语句中判断文件是否可以打开,如果打开文......
  • 实验2 C语言分支与循环基础应用编程
    摘要一、实验目的二、实验准备三、实验内容四、实验结论 task1源代码:1#include<stdio.h>2#include<stdlib.h>3#include<time.h>4#defineN55#defineN13746#defineN246578intmain()9{10intnumber;11inti;12srand(time(0));......
  • 函数基础小结
    函数基础小结计算机的组成之编程什么是编程语言什么是编程为什么要编程计算机的五大组成部分CPU内存外存输入设备输出设备32位和64位多核CPU应用程序的启动机械硬盘的工作原理计算机操作系统什么是文件什么是应用程序操作系统有什么用计算机的三大组成硬件操......
  • Mac OS安装Python的pip
    最近牛牛的同学在学习python,但当他使用numpy时出现了报错(。•́︿•̀。)原因为他的python没有numpy这个库(这个故事很典)。然鹅雪上加霜的是,他的电脑是Mac,没有Windows的cmd...牛牛还没碰过苹果电脑,后面通过查找百度发现在苹果里这玩意儿叫Terminal,经历千辛万苦打开Terminal并开始pip后,......
  • 【Python&GIS】基于Python批量合并矢量数据
    ​老样子最近有项目需要将N个矢量文件合并成一个,总不能用ArcGIS一个个导入吧。所以我就想着用Python编个程序实现批量合并矢量。我之前也发了一些关于Python操作矢量数据的文章:【Python&GIS】Python处理矢量数据的基本操作(查询、修改、删除、新建),如果大家感兴趣可以去我的主......
  • Python深浅拷贝
    Python深浅拷贝拷贝/浅拷贝/深拷贝只针对可变数据类型拷贝(赋值)当lt2为lt的拷贝对象时,lt内的可变类型变化,lt2变化;lt内的不可变类型变化,lt2变化简单的赋值lt=[1,2,3]lt2=ltlt.append(4)print(lt)#因为列表是可变类型,所以lt的值变化,lt2的值也会跟着变化print(l......
  • python设置代理ip,动态代理IP有哪些优势?
    在网络爬虫开发中,使用代理IP是非常常见的技巧,Python作为一门强大的编程语言,也提供了很多方法来使用代理IP,下面,我将就如何在Python中使用代理IP进行详细的阐述,并举例说明,需要的朋友可以参考下。1.方法一:使用urllib模块Python中最基础的网络请求是使用urllib模块,我们可以利用它来使......
  • 【从零学习python 】02. 开发工具介绍及交互式编程及注释详解
    编写Python代码根据我们之前介绍的知识,我们知道,所谓代码其实就是将一段普通文本按照一定的规范编写,然后交给电脑解析并且执行。那既然是一段文本,那我们是否可以直接使用文本编辑器来编码呢?答案是肯定的,但是这样开发起来,效率会很低。一、常见的代码编辑工具实际上,在我们实际工作......