Py学习  »  Python

不永久改变对象的Python方法链接

Goldfishno20 • 6 年前 • 1727 次点击  

return self ,但我不确定如何实现它,以便方法不会对我的原始数据进行变异。

file 具体如下:

+--------+-----+-------+
| Person | Sex | Score |
+--------+-----+-------+
| A      | M   |    10 |
| B      | F   |     9 |
| C      | M   |     8 |
| D      | F   |     7 |
+--------+-----+-------+

MyData 这样我可以做一些基本的数据调用和过滤。

这就是我到目前为止得到的

class MyData:
    def __init__ (self, file):
        import pandas as pd
        self.data = pd.read_excel (file)
        self.Person = self.data['Person']
        self.Sex = self.data['Sex']
        self.Score = self.data['Score']

    def male_only(self):
        self.data = self.data[self.Sex=="M"]
        self.Person = self.Person[self.Sex=="M"]
        self.Score = self.Score[self.Sex=="M"]
        self.Sex = self.Sex[self.Sex=="M"]
        return self

    def female_only(self):
        self.data = self.data[self.Sex=="F"]
        self.Person = self.Person[self.Sex=="F"]
        self.Score = self.Score[self.Sex=="F"]
        self.Sex = self.Sex[self.Sex=="F"]
        return self

这似乎是可行的,但遗憾的是,我的原始数据被这段代码永久地改变了。例如:

Data = MyData(file)
Data.data
>>> Data.data
  Person Sex  Score
0      A   M     10
1      B   F      9
2      C   M      8
3      D   F      7

Data.male_only().data
>>> Data.male_only().data
  Person Sex  Score
0      A   M     10
2      C   M      8

Data.data
>>> Data.data
  Person Sex  Score
0      A   M     10
2      C   M      8

我想要一个返回相同答案的类 Data.male_only().Person Data.Person.male_only() Data.male_only().data Data.data.male_only() 没有永久变异 Data.data Data.Person .

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/54136
文章 [ 3 ]  |  最新文章 6 年前
Demi-Lune
Reply   •   1 楼
Demi-Lune    6 年前

当您编写 self.data = ...

    def male_only(self):
        newdata = MyData()
        newdata.data = self.data[self.Sex=="M"]
        newdata.Person = self.Person[self.Sex=="M"]
        newdata.Score = self.Score[self.Sex=="M"]
        newdata.Sex = self.Sex[self.Sex=="M"]
        return newdata

根据您的评论,这里有一个过滤器解决方案的建议:有一些函数可以激活一些标志/过滤器,然后您必须编写函数来获取属性:

# self.filters should be initialized to [] in __init__
def male_only(self):
    self.filters.append('male_only')
def person(self):
    if "male_only" in self.filters:
        return self.Person[self.Sex=="M"]
    else: 
        return self.Person

为了看看这是否可行,您应该真正完成测试用例,以帮助您修正您的想法(先编写测试用例,然后编写类始终是一个好的实践)。

user10987432
Reply   •   2 楼
user10987432    6 年前

我想详细说明一下“黛米·伦恩”的回答。我不认为有什么方法可以让你创造一个 MyData 实例,修改它,并从链方法返回它。这类方法首先起作用的全部原因是,所有的链式方法都属于同一个类,它们返回该类的一个实例。

str.swapcase , str.zfill str.replace str 他们都回来了 str公司 s。

>>> string = "Hello World"
>>> string.swapcase().zfill(16).replace("L", "T")
'00000hETTO wORTD'
>>> string
'Hello World'
>>> 

Data.Person.male_only() )打破了这个模式,因为现在暗示 male_only 不属于 我的数据 Person 反对。是什么 self.Person self.data["Person"] ? 我对熊猫不是很熟悉。是绳子吗?字符串列表?无论如何,不管它是什么,你想要实现的基本上是添加一个名为 仅限男性 对于那种类型的类。

Kei Minagawa
Reply   •   3 楼
Kei Minagawa    6 年前

我同意@Demi Lune。

我更改了操作码 male_only() female_only() __init__() 方法,因为我认为您不想调用 pd.read_csv() 方法每次创建新对象时。所以 仅限男性() 仅限女性() 方法总是返回新对象,它不会影响其他对象。

import pandas as pd

# Added for creating file on memory.
import io
csv = '''Person,Sex,Score
p1,M,1
p2,M,2
p3,M,3
p4,F,4
p5,F,5
p6,F,6'''
file = io.StringIO(csv)

class MyData:
    def __init__ (self, file=None, data=None):
        import pandas as pd
        if file:
            self.data = pd.read_csv(file)
        else:
            self.data = data
        self.Person = self.data['Person']
        self.Sex = self.data['Sex']
        self.Score = self.data['Score']

    def copy_d(self):
        return MyData(data=self.data.copy())

    def male_only(self):
        d = self.copy_d()
        d.data = self.data[self.Sex=="M"]
        d.Person = self.Person[self.Sex=="M"]
        d.Score = self.Score[self.Sex=="M"]
        d.Sex = self.Sex[self.Sex=="M"]
        return d

    def female_only(self):
        d = self.copy_d()
        d.data = self.data[self.Sex=="F"]
        d.Person = self.Person[self.Sex=="F"]
        d.Score = self.Score[self.Sex=="F"]
        d.Sex = self.Sex[self.Sex=="F"]
        return d

d = MyData(file)
print(d.female_only().data)
#   Person Sex  Score
# 3     p4   F      4
# 4     p5   F      5
# 5     p6   F      6

print(d.male_only().data)
#   Person Sex  Score
# 0     p1   M      1
# 1     p2   M      2
# 2     p3   M      3

print(d.data)
#   Person Sex  Score
# 0     p1   M      1
# 1     p2   M      2
# 2     p3   M      3
# 3     p4   F      4
# 4     p5   F      5
# 5     p6   F      6

但如果你只是在用 pandas.DataFrame ,另一种方法是使用bare . 首先,在大多数情况下, 熊猫.DataFrame Person , Sex Score 因为它已经存在于DATAFRAM对象中。

即:

import pandas as pd
import numpy as np
df = pd.DataFrame(np.eye(3,3), columns=['Person', 'Sex', 'Score'])

# `df` already has these properteis.
df.Person
df.Sex
df.Score
# In [986]: df.Person
# Out[986]: 
# 0    1.0
# 1    0.0
# 2    0.0
# Name: Person, dtype: float64

# In [987]: df.Sex
# Out[987]: 
# 0    0.0
# 1    1.0
# 2    0.0
# Name: Sex, dtype: float64

# In [988]: df.Score
# Out[988]: 
# 0    0.0
# 1    0.0
# 2    1.0
# Name: Score, dtype: float64

所以,你的 仅限男性() 仅限女性() 方法的编写方式如下。

import pandas as pd

# Added for creating file on memory.
import io
csv = '''Person,Sex,Score
p1,M,1
p2,M,2
p3,M,3
p4,F,4
p5,F,5
p6,F,6'''
file = io.StringIO(csv)

def male_only(df):
    return df[df.Sex=='M']

def female_only(df):
    return df[df.Sex=='F']

df = pd.read_csv(file)
male_only(df)
# In [1034]: male_only(df)
# Out[1037]: 
#   Person Sex  Score
# 0     p1   M      1
# 1     p2   M      2
# 2     p3   M      3

female_only(df)
# In [1038]: female_only(df)
# Out[1041]: 
#   Person Sex  Score
# 3     p4   F      4
# 4     p5   F      5
# 5     p6   F      6

我希望它能帮助你。