目录
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的类中存在一些特殊的方法,这些方法都是 __方法__
格式,这种方法在内部均有特殊的含义
__init__
初始化方法,在实例化对象的时候自动执行
class Foo(object):
def __init__(self, name):
self.name = name
obj = Foo("小明")
-
__new__
构造方法,在init方法触发前触发 平时使用会忽略此方法,自动去父类object
中执行__new__
方法创建空对象,可以重写此方法创造单例模式作用:
-
为创建的对象分配内存
-
返回对象的引用
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)
__call__
类创建完对象后,在执行对象时加(),则执行call方法
class Foo(object):
def __call__(self, *args, **kwargs):
print("执行__call__方法")
obj = Foo()
obj() # 对象执行call方法
__str__
把对象转换成字符串,打印对象时,将返回str方法的返回值, 会自动转换
class Foo(object):
def __init__(self, name):
self.name = name
def __str__(self):
return self.name
obj = Foo(name='小明')
print(obj) # 小明
__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}
__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
__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("出去了")"
应用场景: 连接数据库
- 每次对远程的数据进行操作时候都必须经历
-
- 连接 = 连接数据库
-
- 操作数据库
- 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')
"""
__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
__iter__
- 迭代器
# 迭代器类型的定义:
# 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. 练习题
@staticmethod
和@classmethod
的作用
@staticmethod,将一个方法变换为静态方法,静态方法调用的可以是 类也可以是对象,无默认参数
@classmethod,将一个方法变换为类方法,类和方法都可以调用,且cls默认是当前执行该方法的类
- 面向对象如何让成员变为私有
前面加上__
__new__
方法的作用
__new__是构造方法,用于创建对象(空对象),在__init__方法执行之前
- 简述迭代器、生成器、可迭代对象
迭代器: 含有__iter__方法和__next__方法,__iter__返回自身,__next__可以获取数据,没有数据时抛出StopIteration异常,可以被for循环
生成器: 在定义函数时包含yield就是生成器函数,执行函数获得生成器对象(一种特殊的迭代器),可以通过next取值,可以被for循环
可迭代对象: 含有__iter__方法,且返回一个迭代器对象,可以被for循环
- 看代码写结果
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
- 看代码写结果,注意返回值
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)
- 看代码写结果
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') 静态方法不需要参数,通过类和对象都可以调用
- 看代码写结果
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()
- 看代码写结果
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()
- 看代码写结果
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
- 看代码写结果
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())
- 看代码写结果
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)
- 看代码写结果
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)
- 看代码写结果
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)
- 看代码写结果
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)
- 看代码写结果
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__方法
- 补全代码
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()
"""
- 看代码写结果
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()
- 看代码写结果
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) # 广东省
- 分析代码关系,写结果
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