社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

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

Goldfishno20 • 6 年前 • 1881 次点击  

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

我希望它能帮助你。