python基础day08(面向对象)

1.面向对象

如何用面向对象实现某个功能:

1.定义类,在类中定义方法,在方法中实现具体的功能

2.实例化类的一个对象,通过对象去调用并执行方法。


class Message:

    def send_email(self, email, content):
        data = "给{}发邮件,内容是:{}".format(email,content)
        print(data)


msg_object = Message() # 实例化一个对象 msg_object,创建了一个一块区域。
msg_object.send_email("bei@live.com","注册成功")# 调用了send_email这个方法

注意:1.类名称首字母大写&驼峰式命名;2.py3之后默认类都继承object;3.在类种编写的函数称为方法;4.每个方法的第一个参数是self。

1.1对象和self

在每个类中都可以定义个特殊的:__init__ 初始化方法,在实例化类创建对象时自动执行,即:对象=类()

class Message:

    def __init__(self, content):
        self.data = content

    def send_email(self, email):
        data = "给{}发邮件,内容是:{}".format(email, self.data)
        print(data)

    def send_wechat(self, vid):
        data = "给{}发微信,内容是:{}".format(vid, self.data)
        print(data)


# 对象 = 类名() # 自动执行类中的 __init__ 方法。

# 1. 根据类型创建一个对象,内存的一块 区域 。
# 2. 执行__init__方法,模块会将创建的那块区域的内存地址当self参数传递进去。    往区域中(data="注册成功")
msg_object = Message("注册成功")

msg_object.send_email("bj@live.com")  # 给bj@live.com发邮件,内容是:注册成功
msg_object.send_wechat("bj")  # 给bj发微信,内容是:注册成功

通过上述的示例,你会发现:

  • 对象,让我们可以在它的内部先封装一部分数据,以后想要使用时,再去里面获取。

  • self,类中的方法需要由这个类的对象来触发并执行( 对象.方法名 ),且在执行时会自动将对象当做参数传递给self,以供方法中获取对象中已封装的值。

---------------------------------------------------------------------------------------------------------------------------------

  • self,本质上就是一个参数。这个参数是Python内部会提供,其实本质上就是调用当前方法的那个对象。

  • 对象,基于类实例化出来”一块内存“,默认里面没有数据;经过类的 __init__方法,可以在内存中初始化一些数据。

1.2成员

成员分为变量和方法

  • 变量

    • 实例变量

    • 类变量

  • 方法

    • 绑定方法

    • 类方法

    • 静态方法

1.2.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("z", 20)
print(p1.name)
print(p1.age)
print(p1.country)  # 中国

p1.show()  # 中国-z-20

 1.2.2易错点

读和写对的区别

  • 读:优先在自己里边读,没有的再去其他里边读

  • 写:只能在自己里边写

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("z",20)
print(p1.name) # z
print(p1.age) # 20
print(p1.country) # 中国
p1.show() # 中国-z-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 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("z", 19)
print(obj.country)  # 中国
b=Base()
# 写 
Base.country = "china"  # 将Base的country改成china
Person.country = "泰国"  # 在Person 中添加一个country
obj.country = "日本"  # 在obj对象中添加一个country

 1.2.3方法

  • 绑定方法

  • 类方法

  • 静态方法

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("z", 20)
obj.f1()  # Foo.f1(obj)

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

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

1.2.4属性

属性其实是由绑定方法 + 特殊装饰器 组合创造出来的,让我们以后在调用方法时可以不加括号

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)

 属性编写的两种方法

1.基于装饰器的

class C(object):

    @property
    def x(self):
       print("x")

    @x.setter
    def x(self, value):
        print(value)

    @x.deleter
    def x(self):
       print("del")


obj = C()

obj.x
obj.x = 123
obj.x= 777
del obj.x
print(obj.x)

# x
# 123
# 777
# del
# x
# None

 2.基于变量

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  # 报错,错认为你想要调用 @name.setter 装饰的方法。
        self.age = age

    @property
    def name(self):
        return "{}-{}".format(self.name, self.age)


obj = Foo("zz", 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)


obj = Foo("武沛齐", 123)
print(obj._name)
print(obj.name)

1.3成员修改符

  • 公有:可以再任何地方调用这个成员

  • 私有:只能在类中访问成员(私有要在前面加__)

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("zj", 123)


# 公有成员
print(obj.age)
v1 = obj.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()

# 保错 'Foo' object has no attribute '_Foo__data'

正确


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

 1.4对象嵌套

将对象作为参数,传递进去

1.5特殊成员

特殊方法以__方法__格式

  • __init__ 初始化方法
lass Class():
    def __init__(self, name, age):
        self.name = name
        self.age = age


foo = Class("zsj", 18)
  • __call__ 让对象可以执行  
class Class():
   def __call__(self, *args, **kwargs):
       print("""  pppp""")

foo = Class()
foo()
  •  __str__可以让对象返回字符串
class Class():

    def __str__(self):
        return "你们好"


foo = Class()
#data = str(foo)
#print(data)  #

 print(foo)
  •  __dict__将实例变量构造成字典
class Class():

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


foo = Class("zsj", 19)
print(foo.__dict__)##{'name': 'zsj', 'age': 19}
  •  __getitem____setitem____delitem__不同形式的方法调用不同形式的函数
class Class():

    def __setitem__(self, key, value):
        print("{}-{}".format(key, value))

    def __getitem__(self, item):
        print(item)

    def __delitem__(self, key):
        print(key)


foo = Class()
foo["zsj"] = 16  # 自动调用__setitem__方法
foo["zsj"]  # ...  __getitem__
del foo["k3"]  # ... delitem..

# zsj-16
# zsj
# k3
  • __enter__.__exit__  with 对象时 自动先执行 enter with 里的缩进完成时自动执行exit  
class Class():

    def __enter__(self):
        print("进去了")
        return 888  # 返回几f就是几

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("出来了")


foo = Class()
with foo as f:
    print(f)
    print(123)
#进去了
#888
#123
#出来了
  •  __add__可以让两个对象相加时自动执行方法得到一些结果
class Class():
    def __init__(self,name):
        self.name=name

    def __add__(self, other):  # other指想加的第二个对象
        print("{}-{}".format(self.name,other.name))


foo = Class("zsj")
foo2 = Class("牛B")
data = foo + foo2
  •  __iter__ 

1.迭代器

# 迭代器类型的定义:
    1.当类中定义了 __iter__ 和 __next__ 两个方法。
    2.__iter__ 方法需要返回对象本身,即:self
    3. __next__ 方法,返回下一个数据,如果没有数据了,则需要抛出一个StopIteration的异常。 

# 创建 迭代器类型 :
	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()
# 1.
# v1 = obj1.__next__()
# v2 = obj1.__next__()
# v3 = obj1.__next__() # 抛出异常

#2.
# v1 = next(obj1)  # obj1.__next__()
# print(v1)
#
# v2 = next(obj1)
# print(v2)
#
# v3 = next(obj1)
# print(v3)
#3.
obj2 = IT()
for item in obj2:  # 首先会执行迭代器对象的__iter__方法并获取返回值,一直去反复的执行 next(对象)
    print(item)

# 迭代器对象支持通过next取值,如果取值结束则自动抛出StopIteration。
# for循环内部在循环时,先执行__iter__方法,获取一个迭代器对象,然后不断执行的next取值(有异常StopIteration则终止循环)。

 2.生成器

# 创建生成器函数
    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)

如果按照迭代器的规定来看,其实生成器类也是一种特殊的迭代器类。

3.可迭代对象

# 如果一个类中有__iter__方法且返回一个迭代器对象 ;则我们称以这个类创建的对象为可迭代对象。

class Foo(object):
    
    def __iter__(self):
        return 迭代器对象()# 生成器 即实列化对象的类是生成器或迭代器
    
obj = Foo() # obj是 可迭代对象。

# 可迭代对象是可以使用for来进行循环,在循环的内部其实是先执行 __iter__ 方法,获取其迭代器对象,然后再在内部执行这个迭代器对象的next功能,逐步取值。
for item in obj:
    pass

 

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)
v1 = list([11,22,33,44])

v1是一个可迭代对象,因为在列表中声明了一个 __iter__ 方法并且返回一个迭代器对象。


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__且返回迭代器对象。

 

 

 2.三大特性

这种面向对象编程方式有三大特性:封装、继承、多态。

2.1封装

封装主要体现在两个方面:

  • 将同一类方法封装到了一个类中。

  • 将数据封装到了对象中,在实例化一个对象时,可以通过__init__初始化方法在对象中封装一些数据,便于以后使用。

2.2继承

即:子类可以继承父类中的方法和类变量(不是拷贝一份,父类的还是属于父类,子类可以继承而已)。

class Base:

    def func(self):
        print("Base.func")


class Son(Base):

    def show(self):
        print("Son.show")


s1 = Son()
s1.show()
s1.func()  # 优先在自己的类中找,自己没有才去父类。

s2 = Base()
s2.func()
# Son.show
# Base.func
# Base.func

 示列:

。。。

2.3多态

指的是一类事物有多种形态,一个抽象类有多个子类(因而多态的概念依赖于继承),不同的子类对象调用相同的方法,产生不同的执行结果,多态可以增加代码的灵活度

。。。。

2.4补充

在Python3中编写类时,默认都会继承object(即使不写也会自动继承)。

class Foo:
    pass
​
class Foo(object):
    pass

这一点在Python2是不同的:

  • 继承object,新式类

  • 不继承object,经典类

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值