Python学习—面向对象学习下

Python学习—面向对象学习下

面向对象下

1.构造方法与析构方法

class People(object):
    # 构造方法:__init__(),在实例化对象时自动执行的方法
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("创建对象成功.......")
    #  析构函数:__del__(), 当你删除对象时,自动调用的方法
    #  删除对象:del 对象名
    def __del__(self):
        print("删除对象成功.......")

1.构造函数:init()

用于初始化类的内容部状态,也就是当该类被实例化的时候就会执行该函数。那么我们就可以把要先初始化的属性放到这个函数里面。
init()方法是可选的,如果不提供,Python 会给出默认的init方法。一般数据的获取需要定义的get和set方法

2.析构函数:del()

当使用del 删除对象时,会调用他本身的析构函数,另外当对象在某个作用域中调用完毕,在跳出其作用域的同时析构函数也会被调用一次,这样可以用来释放内存空间。
del()也是可选的,如果不提供,则Python 会在后台提供默认析构函数如果要显式的调用析构函数,可以使用del关键字,方式:del 对象名

2.对象的strrepr方法

repr和str这两个方法都是用于显示的,str是面向用户的,而repr面向程序员。
想使用print(Object)显示对象,那就需要重构str。想直接输入类对象Object来打印,那就需要重构repr,当然它也可以使用print(Object)显示对象。区别在于:当你打印一个类的时候,那么print首先调用的就是类里面的定义的str方法,而不是repr方法,在没有str方法时才会去调用repr方法。

#定义类
>>> class Test():
    def __init__(self):
        self.ppx = "hello,python."
#实例化类,然后想直接获取类的一些信息
>>> t = Test()
>>> t
<__main__.Test object at 0x0000000002F3EF28>
>>> print(t)
<__main__.Test object at 0x0000000002F3EF28>

在没有str或者repr方法时,上面打印类对象显示的是对象的内存地址
下面我们重构下该类的repr以及str,看看它们俩的区别

>>> class TestRepr(Test):
    def __repr__(self):
        return "Show:%s"%self.ppx
>>> t1 = TestRepr()
>>> t1
Show:hello,python.
>>> print(t1)
Show:hello,python.

可以看到,重构repr方法后,不管直接输出对象还是通过print打印的信息都按我们repr方法中定义的格式进行显示

>>> class TestStr(Test):
    def __str__(self):
        return "Show:  %s"%self.ppx
>>> t2 = TestStr()
>>> t2
<__main__.TestStr object at 0x00000000031C33C8>
>>> print(t2)
Show:  hello,python.

直接输出对象ts时并没有按我们str方法中定义的格式进行输出,而用print(Object)输出的信息才会这样显示。

3.formate方法

1.通过位置来填充字符串

print("hello %s" % ('world'))

print("hello {0}".format((1, 2, 3, 4)))
print("hello {0} {1} {0} {1}".format((1, 2, 3, 4), "python"))
print("hello {0:.3f}".format(1.8989))

运行输出:
hello world
hello (1, 2, 3, 4)
hello (1, 2, 3, 4) python (1, 2, 3, 4) python

2.通过key来填充

print("max:{max} min:{min}".format(min=10, max=100))

运行输出:
max:100 min:10

3.通过下标/index填充

point = (3,4)
print("x:{0[0]}, y:{0[1]}".format(point))

输出:
x:3, y:4

4.通过字典的key

d = {'max':100.7849758475976, 'min':10.4756895769857985}
print("max:{max:.2f} min:{min:.3f}".format(**d))

运行输出:
max:100.78 min:10.476

5. oop对象进行操作

class Book(object):
    def __init__(self, name, author, state, bookIndex):
        self.name = name
        self.author = author
        # 0:借出 1:未借出
        self.state = state
        self.bookIndex = bookIndex

    # 打印对象时自动调用;str(对象)
    def __str__(self):
        return "书名:{0.name} 状态:{0.state}".format(self)
        # return "书名:{d.name} 状态:{d.state}".format(d=self)

b = Book("java", 'aa', 1, 'Index')
print(b)

运行输出:
书名:java 状态:1

6. 对象中的format魔术方法

# 定义一个存储年月日输出格式的字典
formats = {
    'ymd':"{d.year}-{d.month}-{d.day}",
    'mdy':"{d.month}/{d.day}/{d.year}",
}

class Date(object):
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    # format方法: format(对象名)时自动调用
    def __format__(self, format_spec=None):
        if not format_spec:
            format_spec = 'ymd'
        fmt = formats[format_spec] # "{d.year}-{d.month}-{d.day}".format(d=d)
        return  fmt.format(d=self)

d = Date(2019, 8, 25)
print(format(d))    #不传入参数
print(format(d, 'mdy'))     #传入参数

运行输出:
2019-8-25
8/25/2019

4.关于@property

习惯了高级语言的严谨,总想对属性加以访问控制,相对安全些,比如直接在init中定义公用属性,从封装性来说,它是不好的写法。br/>属性访问控制机制,其一是@propery关键字。用此关键字,其获取、设置函数,须与属性名一致。
@property可以把一个实例方法变成其同名属性,以支持.号访问,它亦可标记设置限制,加以规范,如下代码:

from requests.compat import basestring

class Animal(object):
    def __init__(self, name, age):
        self._name = name
        self._age = age
        self._color = 'Black'

    # 将普通方法变为属性方法
    @property
    def name(self):
        return self._name

    # 当更改name的值时,自动调用下面这个方法。这样就可以更改属性的值了
    @name.setter
    def name(self, value):
        if isinstance(value, basestring):
            self._name = value
        else:
            self._name = 'No name'

    #获取值
    @name.getter
    def get(self):
        return self.name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value > 0 and value < 100:
            self._age = value
        else:
            self._age = 0

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, value):
        self._color = value;

a = Animal('black dog', 3)
a.name = 'white dog'
a.age = 55
a.color = 'red'
print('Name:', a.name)
print('Age:', a.age)
print('Color:', a.color)
print(a.get)

运行结果:
Name: white dog
Age: 55
Color: red
white dog

5.类里面的切片与索引

魔术方法getitemsetitemdelitem
1.对列表的操作

class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores

    # 支持索引; s[index]
    def __getitem__(self, index):
        # print("获取索引对应的value值")
        return  self.scores[index]

    # s[索引] = 修改的值
    def __setitem__(self, index, value):
        self.scores[index] = value

    # del s[索引]
    def __delitem__(self, index):
        del self.scores[index]

    def hello(self):
        return  "hello"
s = Student('westos', [101, 100, 100])

# *********************************索引**************************
print(s[0])
print(s[1])
print(s[2])

#更改值
s[0] = 200
print(s[0])

print(s.scores)
#删除值
del s[0]
print(s.scores)

# *********************************切片**************************
print(s[1:3])
s[1:3] = [0,0]
print(s[:])
del s[:-1]
print(s[:])
print(s[0])

运行结果:
101
100
100
200
[200, 100, 100]
[100, 100]
[100]
[100, 0, 0]
[0]
0

2.对字典的操作

class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores

    # 支持索引; s[key]
    def __getitem__(self, key):
        # print("获取索引对应的value值")
        return  self.__dict__[key]

    # s[key] = 修改的值
    def __setitem__(self, key, value):
        self.__dict__[key] = value

    # del s[key]
    def __delitem__(self, key):
        del self.__dict__[key]

    def hello(self):
        return  "hello"
s = Student('westos', [101, 100, 100])

#**************************key获取value值***********************
print(s.__dict__)
print(s['name'])
print(s['scores'])

s['name'] = 'westo1'
print(s['name'])
del s['name']   #删除一个键值对
# print(s['name'])  #如果查值,会报错:key不存在

运行结果:
{'name': 'westos', 'scores': [101, 100, 100]}
westos
[101, 100, 100]
westo1

6.call()方法

当一个类实现call方法时,这个类的实例就会变成可调用对象。即函数。
1.

class ClassA:

    def __call__(self, *args, **kwargs):
        print('call ClassA instance.......')

# ClassA实现了__call__方法
a = ClassA()
#这个时候,ClassA的实例a,就变成可调用对象
#调用a(),输出call ClassA instance,说明是调用了__call__函数

a()
# 其实a()等同于a.__call__(),它本质上就是后者的缩写
a.__call__()

运行结果:
call ClassA instance.......
call ClassA instance.......

2.

class Dddd(object):
  def __init__(self, origin):
    self.origin = origin
    print("origin :"+str(origin))
  def __call__(self, x):
    print("x :"+str(x))

p = Dddd(100)
p(2000)

运行结果:
origin :100
x :2000

7.实现一个单例模式

class Student(object):
    def __init__(self, name, scores, power):
        self.name = name
        self.scores = scores
        self.power = power

    # 实例化对象之前先执行下面这个new魔术方法
    def __new__(cls, *args, **kwargs):
        # 判断是否obj对象是否已经被创建, 如果没有被创建, 则创建,
        if not hasattr(cls, 'obj'):
            cls.obj = object.__new__(cls)
        # 如果已经创建成功,则返回创建好的对象
        return  cls.obj
s1 = Student('westos1', [101,100,100], 100)
s2 = Student('westos1', [101,100,100], 100)
print(s1)
print(s2)

运行结果:
<__main__.Student object at 0x7fedfa2ebef0>
<__main__.Student object at 0x7fedfa2ebef0>

可以看见,对象s1,s2他们指向的地址相同,即他们时同一个对象。而不是两个相同值的对象。

8.类中的安全上下文with语句

enter()与exit()

class MyOpen(object):
    def __init__(self, filename, mode='r'):
        self._name = filename
        self._mode = mode

    # 当with语句开始运行的时候,执行此方法;
    def __enter__(self):
        self.f = open(self._name, self._mode)
        return  self.f

    # 当with语句执行结束之后运行;
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

with MyOpen('/etc/passwd') as f:
    print(f.closed)
    print(f.read(5))

print(f.closed)

运行如果:
False
root:
True

9.反射

反射:主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)。即 让对象告诉我们相关信息(对象拥有的属性和方法, 对象所属的类等….)

四个可以实现自省的函数

hasattr(object,name)
判断object中有没有一个name字符串对应的方法或属性,注意私有属性或者方法不能判断出来
getattr(object, name, default=None)
获取object中有没有对应的方法和属性,私有属性或者方法不能判断出来不能获取到。default是设置当获取不到时的返回值,默认为None
setattr(x, y, v)
修改或添加对象的属性
delattr(x, y)
删除类或对象的属性

class Student(object):
    """
    这是student类的帮助文档

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

    def get_score(self):
        return  "score"

    def get_grade(self):
        return 'grade'

s1 = Student("fentiao", 10)
print(type(s1))
print(isinstance(s1, Student))
print(isinstance('hello', Student))

#  跟据对象可以获取的内容
print(s1.__class__) #类信息
print(s1.__dict__)  #生成字典
print(s1.__doc__)   #获取帮助文档

#  hasattr, getattr, setattr, delattr
# hasattr: 判断对象是否包含对应的属性或者方法名;
print(hasattr(s1, 'name'))
print(hasattr(s1, '__age'))  # 私有属性, 私有方法, 是不能判断的;
print(hasattr(s1, 'score'))

print(hasattr(s1, 'get_score'))
print(hasattr(s1, 'set_score'))

# getattr
print(getattr(s1, 'name'))
print(getattr(s1, '__age', 'no attr'))
print(getattr(s1, 'get_score', 'no method'))  # 获取方法名, 如果要执行方法, 直接调用即可
print(getattr(s1, 'set_score', 'no method'))  # 获取方法名, 如果要执行方法, 直接调用即可

# setattr:
# 修改某个属性的值
setattr(s1, 'name', 'westos')
print(getattr(s1, 'name'))

# 添加某个属性及对应的值;
setattr(s1, 'score', 100)
print(getattr(s1, 'score'))

# 修改方法
def get_score1():
    return "这是修改的方法内容"
setattr(s1, 'get_score', get_score1)
print(getattr(s1, 'get_score')())

def set_score():
    return  "这是添加的方法"
# 添加方法
setattr(s1, 'set_score', set_score)
print(getattr(s1, 'set_score')())

# delattr
delattr(s1, 'name')
print(hasattr(s1, 'name'))

print(hasattr(s1, 'set_score'))
delattr(s1, 'set_score')
print(hasattr(s1, 'set_score'))

运行结果:
<class '__main__.Student'>
True
False
<class '__main__.Student'>
{'name': 'fentiao', '_Student__age': 10}

    这是student类的帮助文档

True
False
False
True
False
fentiao
no attr
<bound method Student.get_score of <__main__.Student object at 0x7efc6b8a3ac8>>
no method
westos
100
这是修改的方法内容
这是添加的方法
False
True
False

转载于:https://blog.51cto.com/13885935/2171921

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/101439.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 个人能不能开发ctp期货交易_什么是程序化交易期货

    个人能不能开发ctp期货交易_什么是程序化交易期货接触CTP也才半年多,一边学习一边摸索,看到各大CTP的QQ群里,也都是在问一些很菜的问题,就简单总结和介绍下,今天主要是基础知识,即CTP程序的基础和开源的Demo版本:CTP交易接口是由::::::上海期货信息技术有限公司::::::开发的,提供C++的接口,网上也有很多C++的Demo版本,可以直接使用。1:上期所的接口为两个.dll、两个.lib和四个.h文件,初学者可以不要C

  • c++中的排序函数Sort的具体用法(vb中sort函数怎么用)

    最近在刷ACM经常用到排序,以前老是写冒泡,可把冒泡带到OJ里后发现经常超时,所以本想用快排,可是很多学长推荐用sort函数,因为自己写的快排写不好真的没有sort快,所以毅然决然选择sort函数用法1、sort函数可以三个参数也可以两个参数,必须的头文件#include和usingnamespacestd;2、它使用的排序方法是类似于快排的方法,时间复

  • python3 typing_python 高级

    python3 typing_python 高级typing介绍Python是一门弱类型的语言,很多时候我们可能不清楚函数参数的类型或者返回值的类型,这样会导致我们在写完代码一段时间后回过头再看代码,忘记了自己写的函数需要传什么类型的参数,返回什

  • Java基础编程练习题

    Java基础编程练习题很多人在自学java的时候看一遍视频,感觉就会了,课后并没有大量的练习来巩固当前所学的知识点,今天给大家整理了一些非常具有代表意义的题。Java基础类型题1、反转一个只有3位数的整数。从控制台输入321,输出1232、将一个字符由小写字母转换为大写字母。从控制台输入a,输出A3、从控制台输入一个字符串,由字母组成,转换成大写后输出。如果输入的是小写,就转换成大写。…

    2022年10月12日
  • 奇怪的电梯

    奇怪的电梯奇怪的电梯【问题描述】某栋大楼有一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1≤i<N)上有一个数字K(≤K≤N)电梯只有四个按钮:开、关、上、下。上、下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:33125代表了Ki(K1=3,K2=3,…),从一层开始。在一层按“上”可以到4层,按“下”是不起作用的,因为没有-2层。那么从A层到B层至少要按几次按钮呢?【输入格式】第1行为3个用1个空格隔开的正整数,表示N、A、B(l≤N≤200,1≤

  • java中的getClass()方法的用法

    java中的getClass()方法的用法getClass的定义以及使用方法getClass()的作用getClass()使用方式简单代码演示其他相关用法1.getName()和getCanonicalName()2.getDeclaredMethod()3.还有很多对class对象进行操作的方法getClass()的作用getClass()返回此Object的运行时该对象的类.该方法返回一个Class对象,可以通过该对象可…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号